Compare commits

...

675 Commits

Author SHA1 Message Date
(no author)
ea4b3c0748 This commit was manufactured by cvs2svn to create tag
'release_0_6_0'.

git-svn-id: svn://svn.savannah.nongnu.org/qemu/tags/release_0_6_0@1006 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 18:18:20 +00:00
bellard
fbf59244b8 static build fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1005 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 18:18:19 +00:00
bellard
fa36761d7f ppc bios version 0.3
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1004 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:57:29 +00:00
bellard
d08c49aae0 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1003 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:40:19 +00:00
bellard
fcc941fe20 added .cvsignore
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1002 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:28:35 +00:00
bellard
96bcd4f884 Mac OS X port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1001 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:26:15 +00:00
bellard
e3371e62f3 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1000 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:26:02 +00:00
bellard
82eec0a174 Mac OS X port (Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@999 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 16:22:18 +00:00
bellard
933dc6ebc4 Mac OS X port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@998 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:33:29 +00:00
bellard
1e6cae953d comment
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@997 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:31:19 +00:00
bellard
6d463de2b3 removed stdout reference (not portable)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@996 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:28:48 +00:00
bellard
bbbc4663d1 removed unused definitions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@995 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:27:59 +00:00
bellard
02e1ec9bc4 Mac OS X port (Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@994 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 15:15:39 +00:00
bellard
3df3f6fd7b odd memory access fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@993 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 14:45:19 +00:00
bellard
2c6ab8329e load/save state support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@992 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 13:41:46 +00:00
bellard
675376f2b4 kbd save/restore
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@991 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-10 13:39:53 +00:00
bellard
15a34c6364 doc update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@990 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-08 21:26:26 +00:00
bellard
1bfe856eb2 Cirrus VGA is the default - 128 MB default memory - 800x600 default PPC resolution
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@989 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-08 21:17:50 +00:00
bellard
7e71f16f9a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@988 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-08 21:16:21 +00:00
bellard
38a64f9dfe fixed b[l] decoding
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@987 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-07 22:06:01 +00:00
bellard
e02aa6869e suppressed unused function
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@986 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-07 22:04:21 +00:00
bellard
7db4eea691 removed unused code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@985 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-06 20:57:47 +00:00
bellard
b30d4608da 24 bpp fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@984 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-06 01:50:49 +00:00
bellard
81ca79911a 24 bpp mode fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@983 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-06 01:47:47 +00:00
bellard
e58d12ed5b Darwin patch
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@982 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-05 22:13:07 +00:00
bellard
d549f7d98f Darwin patch (initial patch by Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@981 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-05 21:47:44 +00:00
bellard
83fb7adf6c Darwin patch (initial patch by Pierre d'Herbemont)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@980 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-05 21:25:26 +00:00
bellard
1d43a71773 forgot fclose()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@979 c046a42c-6fe2-441c-8c8c-71466251a162
2004-07-05 21:18:42 +00:00
bellard
ae184e4ab7 dac write index register is r/w - CR1D access fix (Volker Ruppert)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@978 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-26 16:13:19 +00:00
bellard
e6eccb38eb dac write index register is r/w (Volker Ruppert)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@977 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-26 16:12:26 +00:00
bellard
9da9886121 fixed case where ram < 16 MB
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@976 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-26 15:53:17 +00:00
bellard
a1968d7196 RT signal may not be a good idea
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@975 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 17:06:27 +00:00
bellard
7f5d44e0ff new Cirrus VGA BIOS from the LGPL'ed VGA BIOS project including VESA support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@974 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 15:02:13 +00:00
bellard
acf5feac80 hlt instruction fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@973 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 14:58:58 +00:00
bellard
d187d4b218 configure BMDMA
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@972 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 14:55:10 +00:00
bellard
9808745072 BMDMA support - CDROM fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@971 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 14:54:19 +00:00
bellard
02ba45c536 use RT signal for /dev/rtc - restore stdin flags (Bob Barry) - cpu save fix (Johannes Schindelin)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@970 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-25 14:46:23 +00:00
bellard
107db44327 consider that all archs have SMC (workaround)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@969 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-22 18:48:46 +00:00
bellard
dc5d0b3d1b disable buggy tb_invalidate_page_range()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@968 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-22 18:43:30 +00:00
bellard
7496f5266c cpu_single_env init
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@967 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-22 10:56:50 +00:00
bellard
91d848ebf3 disable PCI device for PMAC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@966 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 22:46:48 +00:00
bellard
e2733d20b2 ADB fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@965 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 22:46:10 +00:00
bellard
637f6cd735 ppc bios
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@964 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 19:54:47 +00:00
bellard
638260eb8e update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@963 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 19:54:19 +00:00
bellard
30468f786c added PCI bus - added IRQ support for PowerPC bridges - suppressed PREP PCI bios init
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@962 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 19:45:35 +00:00
bellard
46e50e9d58 added PCI bus
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@961 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 19:43:00 +00:00
bellard
7c29d0c0cf dma init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@960 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:58:50 +00:00
bellard
514fb8c10e removed traces
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@959 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:57:45 +00:00
bellard
53c862a88e endianness fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@958 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:56:45 +00:00
bellard
b6b8bd1819 ppc init fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@957 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:55:53 +00:00
bellard
fd0bbb12c3 cmdline init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@956 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:53:42 +00:00
bellard
f2aa58c6f4 UniNorth PCI bridge support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@955 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:52:24 +00:00
bellard
611493d966 openpic fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@954 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:50:43 +00:00
bellard
e1bb04f740 memory mapped NVRAM (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@953 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:49:53 +00:00
bellard
1ade1de223 pmac macio based ide support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@952 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:48:36 +00:00
bellard
b0bda528c3 high page register support for PPC PREP
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@951 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:47:42 +00:00
bellard
819e712bfe cuda fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@950 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:47:13 +00:00
bellard
28b9b5af25 ppc update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@949 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:46:35 +00:00
bellard
e9b137c2dd added -g option for OF initial resolution
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@948 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:46:10 +00:00
bellard
95ea3fa19c added open pic for PPC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@947 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-21 16:44:21 +00:00
bellard
7587cf4401 accept bigger PC BIOSes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@946 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:43:27 +00:00
bellard
7086749072 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@945 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:42:16 +00:00
bellard
63b7e03697 boot to top of 4GB space
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@944 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:38:54 +00:00
bellard
678f2df60f update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@943 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:12:23 +00:00
bellard
9e57f14d60 added APM support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@942 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:06:36 +00:00
bellard
987c1c6921 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@941 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:02:46 +00:00
bellard
ffddfee379 added cpu_reset()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@940 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:01:25 +00:00
bellard
a2f659ee48 new reset API - shutdown support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@939 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 13:00:26 +00:00
bellard
d7d02e3c3a new reset API
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@938 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:58:36 +00:00
bellard
bb0c6722b6 reset and shutdown support - PCI is now the default
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@937 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:37:32 +00:00
bellard
979a54fb20 new reset API
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@936 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:36:04 +00:00
bellard
e4f9082b9a added system_reset command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@935 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:35:44 +00:00
bellard
d95dc32d13 added cpu_reset()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@934 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-20 12:35:26 +00:00
bellard
53ad66e8c3 print error messages if boot error
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@933 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 17:35:07 +00:00
bellard
eba2af633f buffer overflow fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@932 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 17:23:39 +00:00
bellard
95ce326e5b buffer overflow fix - printf format fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@931 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 17:22:53 +00:00
bellard
a5448a7de5 sysinfo syscall (Francois Guimond)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@930 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 16:59:03 +00:00
bellard
9231944d96 sigset_t endianness fix in signal context
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@929 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 16:58:13 +00:00
bellard
d69d1fa01a const fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@928 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-19 16:57:17 +00:00
bellard
05efe46eaa VMware 4 disk images support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@927 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-16 20:34:33 +00:00
bellard
dbda808a4a OpenPIC support (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@926 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-15 21:38:40 +00:00
bellard
a049791855 compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@925 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-14 19:33:16 +00:00
bellard
ea1c18022e fixed self modifying code in case of asynchronous interrupt
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@924 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-14 18:56:36 +00:00
bellard
516633dc42 jump to gate fix (aka OS/2 Warp install bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@923 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-13 15:20:01 +00:00
bellard
dc196a57e3 fixed 16 bit segment optimisations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@922 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-13 13:26:14 +00:00
bellard
2a2820560d IDE ATA identify fix (aka FreeBSD 4.10 fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@921 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-12 22:23:16 +00:00
bellard
665656a99b ffree test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@920 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-12 11:38:00 +00:00
bellard
658c8bdadc added ffree - added cpu log option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@919 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-12 11:35:12 +00:00
bellard
5fef40fb4d added ffree
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@918 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-12 11:34:10 +00:00
bellard
e69390cee7 pattern fill fixes and optimization
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@917 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-09 23:12:09 +00:00
bellard
7f647cf68f IDE1 init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@916 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-09 21:28:36 +00:00
bellard
a130a41e69 interlace support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@915 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-08 00:59:19 +00:00
bellard
78e127efdb set memory size to 4MB for 5446 - fixed memory size probe (aka Win2000 bug) - fixed interlace support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@914 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-08 00:58:26 +00:00
bellard
ee38b4c813 fixed full screen refresh
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@913 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-08 00:56:42 +00:00
bellard
3440557b6d ioport read command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@912 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-08 00:55:58 +00:00
bellard
d329a6fb22 audip fixes (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@911 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 20:58:31 +00:00
bellard
7ebb5e4139 debug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@910 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 20:51:58 +00:00
bellard
57ccbabecb allow 32 but unaligned access (aka Win PCI network bug - initial patch by Renzo Davoli)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@909 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 20:45:42 +00:00
bellard
eb26db16d7 endianness functions for unaligned memory accesses
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@908 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 20:43:57 +00:00
bellard
4c8732d71b cirrus blitter fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@907 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-07 19:46:45 +00:00
bellard
1cc98a5f04 hardware cursor depth = 15 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@906 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 16:06:33 +00:00
bellard
de9258a87f specific VGA BIOS for Cirrus VGA Card
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@905 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 15:50:03 +00:00
bellard
37f53b4c05 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@904 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 15:48:55 +00:00
bellard
a8aa669ba4 generic hardware cursor support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@903 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 15:17:19 +00:00
bellard
a5082316e9 hardware cursor support - fill with rop support - color expand and color expand with transparent support - various optimisations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@902 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-06 15:16:19 +00:00
bellard
20ba3ae101 better to use different ID for ISA and PCI
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@901 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 18:50:58 +00:00
bellard
4c7634bcb3 init VGA with default config
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@900 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 18:49:26 +00:00
bellard
a21ae81d8a change ID to CLGD5446 - added solidfill support - fixed hidden dac access
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@899 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 17:59:37 +00:00
bellard
aeb3c85f59 Cirrus fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@898 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 14:26:11 +00:00
bellard
1f04275ec1 -cirrusvga option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@897 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 13:46:47 +00:00
bellard
4e3e9d0b4d avoid using anonymous struct extension (not supported by all gcc 3.x)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@896 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 13:18:45 +00:00
bellard
358c640721 host bridge config fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@895 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 12:49:34 +00:00
bellard
e36f36e15f mmio support for vga registers - line offset fix - (aka XFree86 4.3.0 fixes)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@894 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 12:47:01 +00:00
bellard
7b17d41e96 Cirrus VGA display fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@893 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 11:06:28 +00:00
bellard
d6bfa22f72 Cirrus VGA emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@892 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 10:32:30 +00:00
bellard
e6e5ad80d8 Cirrus VGA emulation (initial patch by Suzu - heavily modified for easier merge)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@891 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 10:31:55 +00:00
bellard
798b0c25cc generic VGA API layer
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@890 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 10:30:49 +00:00
bellard
22a56b8a87 sdl keyboard fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@889 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-05 08:32:36 +00:00
bellard
44bbf73f92 dhcp packet size fix (aka pump fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@888 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 15:30:48 +00:00
bellard
00ffa62a91 added some keys
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@887 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 13:25:15 +00:00
bellard
de2200d36d fixed window switch - fixed caps lock and num lock - simplified keycodes (initial idea by Mark Jonckheere)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@886 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 13:15:06 +00:00
bellard
710c15a2e9 lmsw fix (aka dos4gw bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@885 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 11:20:49 +00:00
bellard
443f1376bc slirp is enabled by default
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@884 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 11:13:20 +00:00
bellard
a3a91a355b sendkey command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@883 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-04 11:06:21 +00:00
bellard
ab2572d7ea added -fno-strict-aliasing
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@882 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 19:07:57 +00:00
bellard
267002cd28 CUDA + ADB support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@881 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 18:46:20 +00:00
bellard
63066f4f13 hid event handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@880 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 18:45:02 +00:00
bellard
caf9a12e9a CUDA + ADB support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@879 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 18:35:40 +00:00
bellard
1f62d9383f fixed PCI config default write permissions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@878 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 16:40:20 +00:00
bellard
7727994d21 support for opaque data on memory I/Os
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@877 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 14:08:36 +00:00
bellard
8a8696a3c4 support for opaque data on memory I/Os - PCI ROM memory support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@876 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 14:06:32 +00:00
bellard
8998028497 -localtime option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@875 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 14:04:03 +00:00
bellard
a4193c8a4b support for opaque data on memory I/Os
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@874 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 14:01:43 +00:00
bellard
170c6f8705 header fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@873 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 12:53:17 +00:00
bellard
43f493afb4 more accurate emulation (do not depend on localtime() or gmtime()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@872 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 12:51:19 +00:00
bellard
ee22c2f7db -localtime option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@871 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 12:49:50 +00:00
bellard
be3edd9590 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@870 c046a42c-6fe2-441c-8c8c-71466251a162
2004-06-03 12:48:45 +00:00
bellard
023fe10d24 fnop FPU exception support (aka FreeBSD FPU probe) - sysenter/sysexit support (untested, not enabled in cpuid)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@869 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-29 11:08:52 +00:00
bellard
f66723fab9 put ready it after write command (aka FreeBSD HD access fix) - access 16 mult sector count
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@868 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-29 11:04:25 +00:00
bellard
8cc43feffc compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@867 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 23:29:15 +00:00
bellard
09a79b4974 partial big endian fixes - change VESA VBE ports for non i386 targets to avoid unaligned accesses
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@866 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 22:58:01 +00:00
bellard
642012017c PowerPC prep/chrp/pmac support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@865 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 22:55:16 +00:00
bellard
2444ca413b trace fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@864 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 22:16:35 +00:00
bellard
77d4bc349a PowerPC prep/chrp/pmac support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@863 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-26 22:13:53 +00:00
bellard
a2a444d6e0 PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@862 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 22:34:16 +00:00
bellard
4b3686faee PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@861 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 22:18:12 +00:00
bellard
85c4adf65f PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@860 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:25:39 +00:00
bellard
b69fedff84 PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@859 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:17:08 +00:00
bellard
5fd386f698 PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@858 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:11:22 +00:00
bellard
0ced658970 PowerPC merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@857 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:06:12 +00:00
bellard
b415a4078d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@856 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:04:06 +00:00
bellard
f18ac341fe cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@855 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 21:00:55 +00:00
bellard
63ce9e0a42 pci empty device read fix - piix3 ide init
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@854 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 19:12:03 +00:00
bellard
e1c485be84 use PIIX3 like IDE controller
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@853 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 19:10:46 +00:00
bellard
34e538ae5d added PIIX3 like IDE controller - PCI irq generation - SETFEATURES IDE command support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@852 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 19:10:26 +00:00
bellard
9995c51ffd pixx3 ide controller
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@851 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 19:09:22 +00:00
bellard
e58a7c24ac int13 cdrom 32 bit register update fix (aka FreeBSD CDROM boot)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@850 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 16:28:35 +00:00
bellard
777428f2d2 fixed 2.88 MB boot (aka FreeBSD 5.2.1 boot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@849 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-23 16:26:20 +00:00
bellard
5b60212f2a typos (Pavel Janik)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@848 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 21:41:05 +00:00
bellard
a00bad7ed4 default ram size define (Pavel Janik)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@847 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 21:39:06 +00:00
bellard
25b42e9d53 added missing copyright file
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@846 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 18:30:22 +00:00
bellard
8d6c7eb896 receive status register support (aka GRUB netboot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@845 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 16:52:29 +00:00
bellard
7bf5be70f7 pci memory mapping fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@844 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 16:28:18 +00:00
bellard
fb9f944458 PCI BIOS fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@843 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-22 16:27:00 +00:00
bellard
92e873b996 support for non continuous RAM or ROM
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@842 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-21 14:52:29 +00:00
bellard
9fddaa0c0c PowerPC merge: real time TB and decrementer - faster and simpler exception handling (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@841 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-21 12:59:32 +00:00
bellard
4a0fb71e67 irq statistics code (initial patch by Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@840 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-21 11:39:07 +00:00
bellard
274da6b24b 64 bit fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@839 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 21:56:27 +00:00
bellard
15aeac3805 PIC spurious irq support (aka Solaris install bug)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@838 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 16:12:05 +00:00
bellard
28ab0e2edb added cpu_get_tsc()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@837 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 14:02:14 +00:00
bellard
b54ad0498e PIC reset fix (initial patch by Hidemi KAWAI)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@836 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:42:52 +00:00
bellard
4399059e4d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@835 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:24:37 +00:00
bellard
43003046cb BSD fix + ppc-softmmu support for win32
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@834 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:23:39 +00:00
bellard
d157e205e9 win32 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@833 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:22:36 +00:00
bellard
5f21aef2b0 suppressed unneeded header
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@832 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:20:55 +00:00
bellard
829309c70c BSD fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@831 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:20:12 +00:00
bellard
c6a1c22ba6 fixed invalid includes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@830 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:10:49 +00:00
bellard
b71e95fc2c win32 patch (kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@829 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 13:08:06 +00:00
bellard
04a3b84c83 64 bit support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@828 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:51:57 +00:00
bellard
86e0c04896 info pci command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@827 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:49:21 +00:00
bellard
5ce276a11a VGA PCI support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@826 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:48:53 +00:00
bellard
5768f5aca6 PCI interrupt support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@825 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:47:45 +00:00
bellard
1078f663ae dummy VGA PCI support - VGA font selection fix (Daniel Serpell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@824 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:46:38 +00:00
bellard
0ac32c8375 PCI interrupt support - PCI BIOS interrupt remapping - more accurate memory mapping - 'info pci' monitor command
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@823 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:45:00 +00:00
bellard
4a9c9687c6 PCI irq support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@822 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:43:25 +00:00
bellard
73c11f630b cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@821 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:42:19 +00:00
bellard
660de33686 PIIX ELCR register support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@820 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:41:21 +00:00
bellard
69135b5c04 suppressed pci2isa.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@819 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-20 12:40:26 +00:00
bellard
69b910399a PCI support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@818 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-18 23:05:28 +00:00
bellard
158156d13d -user-net is optional - EAGAIN fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@817 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 21:13:42 +00:00
bellard
e63c59cb34 ppc fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@816 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 21:05:06 +00:00
bellard
13ab5daa86 NVRAM fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@815 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 20:21:49 +00:00
bellard
ef792f9ddb added CPU_INTERRUPT_TIMER
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@814 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 20:19:32 +00:00
bellard
47cea614a1 vmdk2raw: convert VMware disk images to raw images
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@813 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 20:06:42 +00:00
bellard
aedf53821f different serial number for each drive (initial patch by Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@812 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-17 19:56:47 +00:00
bellard
7f5e145212 BSR/BSF 'undefined behaviour' test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@811 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 16:02:40 +00:00
bellard
f528bfd45d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@810 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 15:57:26 +00:00
bellard
686f3f266b BSR/BSF undefined behaviour fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@809 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 15:56:04 +00:00
bellard
5b1214a48e int15, ah=86 BIOS fix (aka Solaris x86 hardware probe hang up fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@808 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 15:52:12 +00:00
bellard
3f433d2c87 int13 CDROM BIOS fix (aka Solaris x86 install CD fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@807 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-16 14:21:17 +00:00
bellard
1a084f3d51 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@806 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-13 22:34:49 +00:00
bellard
cd6f11693a custom option parsing to have same behavior on all OSes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@805 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-13 22:02:20 +00:00
bellard
b939777cec floppy fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@804 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 22:07:40 +00:00
bellard
d6b86f4d85 -tun-fd option fix (Renzo Davoli)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@803 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:59:20 +00:00
bellard
3a1bc175ea allow '-nics 0'
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@802 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:54:43 +00:00
bellard
db45c29a65 faster I/Os - default 16 bit I/O fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@801 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:50:26 +00:00
bellard
7d3505c55a bsd port (Markus Niemisto)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@800 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:32:15 +00:00
bellard
fd872598d8 primitive ioport debug - /dev/rtc fast timer support (needed for better simulation accuracy with Linux 2.4)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@799 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:11:15 +00:00
bellard
8cd0ac2fe1 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@798 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 19:09:16 +00:00
bellard
7efa43875d better packaging support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@797 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-12 18:54:06 +00:00
bellard
44c513c4c9 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@796 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:24:35 +00:00
bellard
2ee73ac3a8 division by zero FPU exception support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@795 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:08:41 +00:00
bellard
28c3ee3fed cr0.ET fix (Win95 boot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@794 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:05:19 +00:00
bellard
f929aad6e3 MSDOS compatibility mode FPU exception support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@793 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:03:41 +00:00
bellard
e309de25a6 SPECIFY command fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@792 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:01:23 +00:00
bellard
10d315a8f2 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@791 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 21:00:00 +00:00
bellard
2b64948eb5 64 bit fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@790 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 15:27:20 +00:00
bellard
1f50f8d1d4 better install
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@789 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 14:44:43 +00:00
bellard
a1b74fe8fe update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@788 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 13:26:35 +00:00
bellard
ed5fd2cce4 timer for READ_ID (win98 floppy fix) - simpler irq handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@787 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-08 13:14:18 +00:00
bellard
bee3290936 typo
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@786 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-05 18:50:02 +00:00
bellard
beddab753d arm load/store half word fix (Ulrich Hecht)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@785 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-05 18:36:10 +00:00
bellard
512176dbd8 fixed dhcp for windows client
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@784 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-04 03:14:47 +00:00
bellard
fb6cf1d09c fixed floppy reset (aka win98 floppy probe fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@783 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-04 02:04:17 +00:00
bellard
66201e2ddf ide slave fixes (aka Win98 CD-ROM detection fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@782 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-04 01:29:51 +00:00
bellard
ec844b96c0 pit fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@781 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-03 23:18:25 +00:00
bellard
f72e8ff4a6 utime fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@780 c046a42c-6fe2-441c-8c8c-71466251a162
2004-05-03 19:23:07 +00:00
bellard
b06eddd39d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@779 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 22:34:24 +00:00
bellard
6f51f6b593 keyboard irq generation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@778 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 22:23:55 +00:00
bellard
0294ffb9c8 disable grab if the window no longer has the focus (Windows case) (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@777 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 22:15:15 +00:00
bellard
d8d8aa4e2c SDL static config fix (Roman Zippel)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@776 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 20:14:07 +00:00
bellard
141253b254 Bochs VBE emulation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@775 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-29 19:21:16 +00:00
bellard
646be93b4c Bochs VBE emulation fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@774 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-28 22:38:47 +00:00
bellard
26aa7d72cc isa memory remapping support (aka PPC PREP VGA support)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@773 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-28 22:26:05 +00:00
bellard
8e9c4afe70 full screen support (initial patch by malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@772 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-28 19:33:40 +00:00
bellard
bbc9d34839 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@771 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 21:15:11 +00:00
bellard
a8c490cda5 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@770 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 20:59:17 +00:00
bellard
4606bb3f06 copyright update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@769 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 20:58:11 +00:00
bellard
aaaa7df625 added temporary option -enable-audio
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@768 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 20:56:53 +00:00
bellard
9d4fb82e3c update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@767 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 20:55:38 +00:00
bellard
9fafc9eaf0 avoid errno variable name
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@766 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:50:09 +00:00
bellard
1ef59d0acf ppc fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@765 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:48:05 +00:00
bellard
7fd7b91fac amd64 port
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@764 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:46:45 +00:00
bellard
d927637dca init dummy net if tun/tap network error
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@763 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:44:57 +00:00
bellard
4f2ac23784 amd64 port (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@762 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-26 19:44:02 +00:00
bellard
f658b4db79 isa bridge endianness fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@761 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 22:10:09 +00:00
bellard
0c4ad8dc2a ide endianness fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@760 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 22:09:16 +00:00
bellard
165c6fc8ce more endianness macros
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@759 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 22:08:49 +00:00
bellard
2e12669a4c consistent use of target_ulong and target_phys_addr_t
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@758 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:28:44 +00:00
bellard
52c00a5f15 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@757 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:27:03 +00:00
bellard
ab6d960ffa added target_phys_addr_t
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@756 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:25:15 +00:00
bellard
fbf9eeb34d added cpu_resume_from_signal() - irq fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@755 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:21:33 +00:00
bellard
046d6672e2 avoid unneeded casts
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@754 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 21:15:35 +00:00
bellard
75dfaa1e64 x86-64 port (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@753 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 19:04:19 +00:00
bellard
1115dde719 x86-64 port (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@752 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:57:49 +00:00
bellard
57206fd42a more register values in monitor
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@751 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:54:52 +00:00
bellard
4c27ba27c5 added 'info pic' - added 16/32 bit x86 instruction dump
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@750 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:05:08 +00:00
bellard
ba91cd80d5 fixed very unlikely irq bug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@749 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:03:53 +00:00
bellard
6f1f31c069 ARM cache flush support (untested) - '-d' option fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@748 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 18:00:45 +00:00
bellard
5467a72294 disabled S3 VGA
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@747 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:59:00 +00:00
bellard
1b8eb456eb avoid error if too many sectors in non LBA mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@746 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:58:25 +00:00
bellard
d720b93d0b precise self modifying code support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@745 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:57:43 +00:00
bellard
eeab3a558f dump A20 state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@744 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:56:46 +00:00
bellard
658138bcbc flush insn support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@743 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:56:08 +00:00
bellard
1190935d98 precise self modifying code test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@742 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 17:54:32 +00:00
bellard
bfbc9133eb 64 bit seek for win32 (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@741 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-25 14:43:10 +00:00
bellard
ad6a4837f8 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@740 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-24 00:16:28 +00:00
bellard
039d3da365 added user mode libqemu usage example
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@739 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-24 00:11:51 +00:00
bellard
a7e61ed446 create slirp directory
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@738 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 21:46:47 +00:00
bellard
b5075d29a8 more imul tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@737 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 21:37:55 +00:00
bellard
91caaa612a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@736 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 21:36:13 +00:00
bellard
d64477afa1 imul imm8 fix - 0x82 opcode support (Hidemi KAWAI)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@735 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 21:34:25 +00:00
bellard
f6bac3809f fixed options definition
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@734 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 00:35:09 +00:00
bellard
f0cbd3ec9f initial user mode network support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@733 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 00:10:48 +00:00
bellard
7c1f25b46a probe static SDL link
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@732 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-22 00:02:08 +00:00
bellard
ee9dbb297d NE2000 fixes for windows (Renzo Davoli)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@731 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-21 23:29:33 +00:00
bellard
c20709aa32 initial user mode network support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@730 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-21 23:27:19 +00:00
bellard
92cb7d5423 NT mouse fix (Mark Jonckheere)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@729 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-16 22:17:49 +00:00
bellard
202a456a2b safer sb16 code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@728 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-16 22:09:02 +00:00
bellard
3294b949eb avoid segfault if transient invalid text resolution
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@727 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-15 22:35:16 +00:00
bellard
2aebb3eb2b blanking support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@726 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-15 22:28:04 +00:00
bellard
95917e3f57 suppressed no longer needed vm86 segment hack (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@725 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-15 22:13:27 +00:00
bellard
f186904281 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@724 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-12 20:58:23 +00:00
bellard
c5df018e56 ppc: suppressed unneeded globals and headers - added explicit type for ppc nvram
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@723 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-12 20:54:52 +00:00
bellard
a541f297a3 PowerPC system emulation fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@722 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-12 20:39:29 +00:00
bellard
df475d18d8 fixed invalid command test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@721 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-12 19:07:27 +00:00
bellard
2f0c934ef9 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@720 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-11 14:55:01 +00:00
bellard
fd836909df VM86 EIP masking fix (aka NT5 install fix) (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@719 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-11 14:54:42 +00:00
bellard
289e09e77b fixed keyboard random bug (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@718 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-10 19:04:48 +00:00
bellard
7ae9862745 ide select logic fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@717 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 22:13:51 +00:00
bellard
41b9be476c preserve partition table when using -linux option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@716 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 21:30:08 +00:00
bellard
52302d7274 fix the no device case
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@715 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 21:01:17 +00:00
bellard
333190eb97 base memory size in cmos
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@714 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 20:51:30 +00:00
bellard
eccabc6ee0 vga 9 pixel wide text char fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@713 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 20:31:38 +00:00
bellard
bb058620c3 refuse write accesses in BIOS area (aka EMM386.EXE fix) (Mike Nordell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@712 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-07 20:21:16 +00:00
bellard
9eb153f18f dma clean up - added missing read accesses
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@711 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-06 22:43:01 +00:00
bellard
aaba6c1516 win32: correct keycode remapping
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@710 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-06 19:30:16 +00:00
bellard
38e205a25b win32: do not use all cpu time
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@709 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-06 19:29:17 +00:00
bellard
e1a237441d port 92 access
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@708 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-05 20:26:03 +00:00
bellard
57c3072482 fixing free
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@707 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 20:36:29 +00:00
bellard
73332e5ccd qemu fast fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@706 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 20:22:28 +00:00
bellard
1f673135ac doc update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@705 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 15:21:17 +00:00
bellard
aa455485c9 history support (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@704 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 13:07:25 +00:00
bellard
9307c4c1d9 improved monitor: type check, expression evaluator, memory dump, disassembly
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@703 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 12:57:25 +00:00
bellard
40c3bac35a win32 port (Kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@702 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 12:56:28 +00:00
bellard
6eaee46144 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@701 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 12:55:00 +00:00
bellard
0f2f112156 tun-fd fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@700 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-04 09:37:47 +00:00
bellard
4721c45750 UIP update fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@699 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-03 12:27:31 +00:00
bellard
a6e022ad13 fixed SDL probing for cross compilation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@698 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 21:55:47 +00:00
bellard
702c651c4a added -macaddr option
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@697 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 21:21:32 +00:00
bellard
1154e441aa avoid rounding problems
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@696 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 20:58:56 +00:00
bellard
e463b581ea rdtsc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@695 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 20:57:58 +00:00
bellard
11d9f695e7 win32 cross compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@694 c046a42c-6fe2-441c-8c8c-71466251a162
2004-04-02 20:55:59 +00:00
bellard
0c607d5728 win32 port (initial patch by kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@693 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 23:54:52 +00:00
bellard
67b915a5dd win32 port (initial patch by kazu)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@692 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 23:37:16 +00:00
bellard
bb27c19087 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@691 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 19:05:07 +00:00
bellard
8a7ddc38a6 new timer API - new API to save/restore the virtual machine state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@690 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 19:00:16 +00:00
bellard
b0a21b5334 use new timer API
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@689 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 18:58:38 +00:00
bellard
dff38e7b40 more precise RTC emulation (periodic timers + time updates)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@688 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 18:57:29 +00:00
bellard
1f1af9fd7f added cpu_get_fp80() and cpu_set_fp80()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@687 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 18:56:43 +00:00
bellard
858693c638 moved gdbstub to qemu - new asynchronous gdbstub
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@686 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-31 18:52:07 +00:00
bellard
9b14bb04ca install fix (Rusty Russel)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@685 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-26 22:43:34 +00:00
bellard
c101c49c54 added qemu-mkcow man page
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@684 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-26 22:42:54 +00:00
bellard
4bb2fcc7c9 gcc 2.95.4 compile fix (Petter Reinholdtsen)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@683 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-26 22:38:57 +00:00
bellard
08cea4eef8 fixed ljmp and iret to TSS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@682 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-26 22:26:53 +00:00
bellard
883da8e219 task switch fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@681 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-24 00:50:26 +00:00
bellard
78ebca6e13 fixed IDE probe
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@680 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-23 22:42:43 +00:00
bellard
5e2a644399 removed most of global context uses - removed unneeded abort() which cause problems during win95 hardware scan
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@679 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-23 22:42:11 +00:00
bellard
11774f549e protected lret x86 'bug' emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@678 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 18:28:57 +00:00
bellard
d9d849fc5d update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@677 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 17:12:48 +00:00
bellard
e19e89a5d4 more log items
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@676 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 17:08:23 +00:00
bellard
f193c7979c do not depend on thunk.h - more log items
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@675 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 17:06:25 +00:00
bellard
3035f7ff83 use new directory layout
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@674 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-21 17:02:00 +00:00
bellard
4afa64828b fixed protected lret imm insn (one more OS/2 fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@673 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-20 22:04:16 +00:00
bellard
c45c3d0059 write to both IDE drives - return 0 for not present drives
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@672 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-20 22:01:15 +00:00
bellard
baca51faff updated floppy driver: formatting code, disk geometry auto detect (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@671 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-19 23:05:34 +00:00
bellard
bc51c5c989 initial x86-64 host support (Gwenole Beauchesne)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@670 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-17 23:46:04 +00:00
bellard
5069146392 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@669 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-17 23:44:10 +00:00
bellard
59a983b921 device independent VGA screen dump
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@668 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-17 23:17:16 +00:00
bellard
4e463d8d50 tun-fd option fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@667 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-16 00:02:58 +00:00
bellard
94fe4f9fa3 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@666 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:49:05 +00:00
bellard
0fb48229a7 added qemu_mallocz()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@665 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:48:47 +00:00
bellard
b41a2cd1e4 io port API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@664 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:46:48 +00:00
bellard
c4b1fcc0f9 added I/O API - io port API change - added multiple network interface support - redirect serial port to a pseudo terminal if using graphical mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@663 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:44:30 +00:00
bellard
0f35920cd8 io port API change - removed dumb console redraw (not useful)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@662 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:42:10 +00:00
bellard
7d977de7e1 io port API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@661 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:41:34 +00:00
bellard
07d898662d added qemu_mallocz()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@660 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:41:12 +00:00
bellard
caed880216 removable device support - io port API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@659 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:40:43 +00:00
bellard
b338082b3f remoable device support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@658 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:38:54 +00:00
bellard
9dc39cbae3 added a command line monitor
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@657 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 21:38:27 +00:00
bellard
80cabfad16 separated more devices from emulator
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@656 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-14 12:20:30 +00:00
bellard
38ca2abc2e m68k compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@655 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-13 18:32:13 +00:00
bellard
73bdea1951 2.6 kernel compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@654 c046a42c-6fe2-441c-8c8c-71466251a162
2004-03-04 22:50:52 +00:00
bellard
00af2b2680 added cow.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@653 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-26 00:20:56 +00:00
bellard
a735aa3139 added precompiled linux boot sector
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@652 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:54:25 +00:00
bellard
6b2b6112f8 more FPU context save tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@651 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:34:07 +00:00
bellard
bf08806145 native FPU support in code copy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@650 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:33:36 +00:00
bellard
f9e92e973f use physical memory access functions for DMA
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@649 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:32:01 +00:00
bellard
8dc75d7535 moved DMA and SB16 outside timer (may break SB16)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@648 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:30:56 +00:00
bellard
03857e318e native FPU support in code copy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@647 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:26:33 +00:00
bellard
16f62432c4 DMA API change
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@646 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:25:55 +00:00
bellard
8b1f24b090 new physical memory access API (used by DMA accesses)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@645 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:24:38 +00:00
bellard
b448f2f36c new physical memory access API (used by DMA accesses) - code copy FP fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@644 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:24:04 +00:00
bellard
97eb5b14dc native FPU support in code copy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@643 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:19:55 +00:00
bellard
7eee2a509a CR0.MP/EM/TS support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@642 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:17:58 +00:00
bellard
42c3c0cced native FPU support (disabled)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@641 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:17:25 +00:00
bellard
9588b95a08 CR0.MP/EM/TS support - native fpu support in code copy mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@640 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:15:55 +00:00
bellard
2edcdce334 fpu fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@639 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-25 23:15:06 +00:00
bellard
8853f86e1d shm support, more setsockopt and getsockopt calls, fds fix (initial patch by Paul McKerras)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@638 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 14:57:26 +00:00
bellard
e374bfa35b shm tests - disabled clone test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@637 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 14:54:18 +00:00
bellard
b88e4a9a3b small test optimisations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@636 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 13:41:47 +00:00
bellard
537730b956 zero offset optimisation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@635 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 13:40:57 +00:00
bellard
edf779ffcc use kernel like macros for user access (will be useful someday to have a better error checking
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@634 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 13:40:13 +00:00
bellard
121061dcdf O_DIRECT compile fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@633 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 11:56:01 +00:00
bellard
83d7396850 faster big endian accesses on i386 - big endian ldsw_raw fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@632 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-22 11:53:50 +00:00
bellard
6b2d3e3c96 fixed blr/bctr cases
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@631 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 15:41:09 +00:00
bellard
e98a6e40a9 adding direct block chaining support - simplified branch code gen
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@630 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 15:35:00 +00:00
bellard
28fbe299c3 lwarx fix (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@629 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 14:13:13 +00:00
bellard
297d8e6227 Fix check for lswi (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@628 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 14:11:27 +00:00
bellard
004bc62c28 update nip when processing exceptions (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@627 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-21 14:10:04 +00:00
bellard
ed1c0bcb0c use osdep.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@626 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:17:43 +00:00
bellard
22a46c55e4 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@625 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:13:24 +00:00
bellard
ea88812f4f added OS dependent functions (temporary as most functions are generic in fact)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@624 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:12:40 +00:00
bellard
58fe2f10f0 experimental code copy support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@623 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:11:32 +00:00
bellard
3a1d9b8bbb fixed lea exception
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@622 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:10:33 +00:00
bellard
0e4b179d33 experimental code copy support - fixed A20 emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@621 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:08:32 +00:00
bellard
77fef8c148 experimental code copy support - added new Linux kernel loader
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@620 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:05:46 +00:00
bellard
59817ccb2c use qemu memory allocation - added dirty bit support when using host MMU
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@619 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 22:01:13 +00:00
bellard
bf3e8bf11e experimental code copy support - CPU_INTERRUPT_EXITTB support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@618 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:58:54 +00:00
bellard
9acbed0605 added CPU_INTERRUPT_EXITTB and code_copy_enabled
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@617 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:57:02 +00:00
bellard
cf98951b82 force boot sector feature
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@616 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:56:36 +00:00
bellard
f72b519c86 added osdep.o and nwfpe
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@615 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:55:35 +00:00
bellard
07ce05eaa9 fast Linux boot support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@614 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:55:09 +00:00
bellard
b324e814a9 suppressed unused variables
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@613 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:54:14 +00:00
bellard
c69810559b arm nwfpe support - added code no-code-copy option - __preinit_array_start bug fix (untested)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@612 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:49:03 +00:00
bellard
28c4f361ac arm nwfpe support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@611 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:47:43 +00:00
bellard
3d57da2a70 suppressed dummy FPU ops
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@610 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:47:14 +00:00
bellard
00406dff19 added arm nwfpe support (initial patch by Ulrich Hecht)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@609 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:43:58 +00:00
bellard
69de927c6c arm nwfpe support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@608 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 21:40:43 +00:00
bellard
72cbca10e1 direct chaining support for SPARC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@607 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-16 20:30:05 +00:00
bellard
34f715e754 fixed WP semantics
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@606 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-07 20:42:14 +00:00
bellard
cae61cef89 bochs vbe: virtual screen support and bank switch (untested)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@605 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 23:58:08 +00:00
bellard
6411cfb6f3 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@604 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 19:57:09 +00:00
bellard
898712a85c sdl_cleanup fix (Martin Garton)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@603 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 19:56:42 +00:00
bellard
4fa0f5d292 added bochs VBE support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@602 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 19:47:52 +00:00
bellard
1ccde1cb94 added generic physical memory dirty bit support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@601 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-06 19:46:14 +00:00
bellard
ad08132319 added tlb_flush() flags
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@600 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:39:42 +00:00
bellard
415e561f1d cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@599 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:37:12 +00:00
bellard
ee8b7021da temporary interrupt locking fix (need rework)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@598 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:35:10 +00:00
bellard
625976dac8 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@597 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:30:47 +00:00
bellard
1ac157da77 more precise TLB invalidation - init cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@596 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:28:30 +00:00
bellard
64a595f26a cleanup
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@595 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-03 23:27:13 +00:00
bellard
3ad9a57e4f ide identify fix (initial patch by Jens Axboe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@594 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-01 17:55:47 +00:00
bellard
7f777bf385 fixed atapi error codes (initial patch by Jens Axboe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@593 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-01 17:37:48 +00:00
bellard
56bf1d37a0 SEEK_STAT bit ata reset fix (Jens Axboe)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@592 c046a42c-6fe2-441c-8c8c-71466251a162
2004-02-01 17:24:11 +00:00
bellard
c92b2e845f vga memory address fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@591 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-27 00:14:11 +00:00
bellard
68e73e391f clean tests dir
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@590 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-25 15:47:27 +00:00
bellard
c0637b3794 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@589 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-25 15:38:01 +00:00
bellard
e98c87213e update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@588 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-25 15:26:12 +00:00
bellard
3d4b4c0f4b update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@587 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-25 15:22:15 +00:00
bellard
8145122b08 correct NT flag behavior - zero ldt task switch bug fix - task switch thru call insn bug fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@586 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 16:27:56 +00:00
bellard
7399c5a9be fixed eflags optimisations with string operation (aka linux 2.6.2rc1 fix) - removed warnings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@585 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 16:24:06 +00:00
bellard
10f0e412f8 combine PDE and PTE protections as in intel specs - added cpu_get_phys_page_debug()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@584 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:29:03 +00:00
bellard
4b7aba5173 correct NT flag behavior
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@583 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:27:58 +00:00
bellard
35b66fc4f9 correct target_ulong definition
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@582 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:26:06 +00:00
bellard
13eb76e091 virtual memory access for gdbstub
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@581 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:23:36 +00:00
bellard
3cf1e035ba added TARGET_LONG_BITS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@580 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:19:09 +00:00
bellard
a6b025d37d added cpu_get_phys_page_debug()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@579 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:18:16 +00:00
bellard
edfcbd9937 added cpu_get_phys_page_debug()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@578 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:11:05 +00:00
bellard
612b477d48 removed warnings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@577 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 15:10:18 +00:00
bellard
6c9bf8936a update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@576 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 13:46:56 +00:00
bellard
bb551faa4a increased physical RAM limit to 2047 MB in soft MMU mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@575 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-24 13:42:26 +00:00
bellard
a136e5a8b1 ATAPI transfer size fix (NetBSD CDROM access fix) - added WIN_CHECKPOWERMODE1 - set error to zero in some cases
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@574 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-22 23:52:27 +00:00
bellard
4796f5e9bc interrupt to conforming segment fix (QNX boot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@573 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-19 23:46:39 +00:00
bellard
3504fe171b 16 bit DMA fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@572 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-19 21:11:02 +00:00
bellard
ab1f142ba0 L4 fix for rep nop (should handle all cases)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@571 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-19 20:31:37 +00:00
bellard
4120b61d00 test at least one invalid lock op code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@570 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-19 20:29:34 +00:00
bellard
7f957d280b PowerPC merge (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@569 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 23:19:48 +00:00
bellard
2be3bc02dd update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@568 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 23:14:25 +00:00
bellard
c27357906a avoid exiting directly if file not found
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@567 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:55:23 +00:00
bellard
985a19d6d1 PowerPC merge (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@566 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:49:57 +00:00
bellard
3f5dcc340c PowerPC merge (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@565 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:44:01 +00:00
bellard
f09936ac82 ARM fcntl flag fixes (Lennert Buytenhek)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@564 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:39:25 +00:00
bellard
d030931173 automatic floppy boot
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@563 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:35:25 +00:00
bellard
825bd5f8e5 temporary gcc 3.3 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@562 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:25:49 +00:00
bellard
bc0b1dc1eb sb16 patch (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@561 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:19:31 +00:00
bellard
630be16f6c alpha fix (Falk Hueffner)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@560 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:06:47 +00:00
bellard
44a91cae10 suppressed cast to lvalue
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@559 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 22:05:44 +00:00
bellard
d575b78aab more xadd tests - cmpxchg8b test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@558 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:57:29 +00:00
bellard
6e44ba7fa2 cmos return current date - current irq priority in PIC (L4 Pistachio support) - help fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@557 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:56:49 +00:00
bellard
6986f88c3f cast to return type
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@556 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:53:18 +00:00
bellard
988578886e fixed tlb invalidation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@555 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:52:14 +00:00
bellard
c4c7e3e610 ppc code gen size fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@554 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:50:28 +00:00
bellard
b516f85ca8 simpler second page physical address test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@553 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:50:04 +00:00
bellard
1e4fe7cee2 fixed potential exception pb on cmpxchg
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@552 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:44:40 +00:00
bellard
debf7a7c7e comments fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@551 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:43:36 +00:00
bellard
5a1388b6df xadd fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@550 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:41:29 +00:00
bellard
777aca2fd3 fixed dirty bit support for 4M pages (L4 Pistachio fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@549 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:39:51 +00:00
bellard
69e5bc9068 generate read error if no image (win XP install boot)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@548 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-18 21:37:47 +00:00
bellard
c8135d9af6 fixed subtle bug: in some cases PG_DIRTY was not set correctly
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@547 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-13 00:00:25 +00:00
bellard
9e62fd7f26 ppc support (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@546 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 22:49:06 +00:00
bellard
8977f3c107 Floppy disk emulation (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@545 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:09:06 +00:00
bellard
728c9fd5a9 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@544 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:08:14 +00:00
bellard
bd49793889 use generic GenOpFunc
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@543 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:06:41 +00:00
bellard
16d17fdb8e debug fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@542 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:05:50 +00:00
bellard
4487d0ac49 changed cpu_x86_in/out to cpu_in/out
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@541 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:05:04 +00:00
bellard
7138fcfbf7 use CPUState
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@540 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:02:28 +00:00
bellard
c45886db19 PowerPC system emulation (Jocelyn Mayer) - PIC poll mode (Jocelyn Mayer) - use CPUState - Floppy support (Jocelyn Mayer) - command line debug (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@539 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-05 00:02:06 +00:00
bellard
ffa65c3b70 fcntl flags convertion (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@538 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:57:22 +00:00
bellard
2d603d2216 PowerPC support - float macros
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@537 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:56:24 +00:00
bellard
61190b14fc PowerPC update (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@536 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:54:31 +00:00
bellard
9886cc165a factorized GenOpFunc
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@535 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:53:54 +00:00
bellard
ce09776be2 PowerPC System emulation (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@534 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:53:18 +00:00
bellard
5be1a8e065 ppc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@533 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:51:58 +00:00
bellard
09683d3597 changed cpu_x86_in/out to cpu_in/out
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@532 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:49:41 +00:00
bellard
590b7eed18 aalib support with SDL
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@531 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:49:02 +00:00
bellard
af5ad10728 infer access type
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@530 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:28:12 +00:00
bellard
ac9eb0731a suppressed explicit access type and use the exception routine to infer it from the micro operation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@529 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 23:26:24 +00:00
bellard
9a64fbe4d8 PowerPC system emulation (Jocelyn Mayer) - modified patch to use new TLB api
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@528 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 22:58:38 +00:00
bellard
efe160c502 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@527 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:28:47 +00:00
bellard
dc887a4dae make the bios be a ROM memory - glibc hacks for setvbuf and signals - correct century storage in CMOS emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@526 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:18:57 +00:00
bellard
b9f1950797 hack for target_ulong define
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@525 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:17:13 +00:00
bellard
e16c53fabb assembly soft MMU defines on i386
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@524 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:15:29 +00:00
bellard
8351d2d481 WHEEL defines may not be available in SDL
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@523 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:15:01 +00:00
bellard
08785f48b7 updated so that PPC/ARM/SPARC executables are automatically launched when invoked
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@522 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:12:46 +00:00
bellard
75c6215f98 correct cpu state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@521 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:08:37 +00:00
bellard
6b136f9e8f CD-ROM detection fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@520 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:08:12 +00:00
bellard
2ddbbd10de (temporary) only physical dump is possible in gdb
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@519 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:07:27 +00:00
bellard
9fa3e85353 new generic TLB support - faster self modifying code support - added ROM memory support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@518 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:06:42 +00:00
bellard
4390df5107 added support for direct patching on i386 host (faster emulation) - increased translation buffer size - added new TLB support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@517 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 18:03:10 +00:00
bellard
ecd854fdb4 added support for direct patching on i386 host (faster emulation)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@516 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:45:05 +00:00
bellard
513b500f75 include stddef.h for size_t definition
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@515 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:44:08 +00:00
bellard
edf75d592c export more memory defines
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@514 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:43:30 +00:00
bellard
1376847f9f support for new TLB handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@513 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:43:01 +00:00
bellard
17348a7f5e waiting for TARGET_HAS_SMC patch
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@512 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:36:11 +00:00
bellard
4f31916ffb added raw/user/kernel memory accesses for shifts/adc/sbb/cmpxchg/push/pop (faster emulation) - make 'call Ev' exception safe - in/out dx fix - PE flag is static
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@511 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:35:00 +00:00
bellard
943144d91a added raw/user/kernel memory accesses (faster emulation)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@510 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:31:11 +00:00
bellard
34e01bbf07 fixed dx based protected in/outs (win98 install) - changed JUMP_TB2 branch number arg
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@509 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:30:14 +00:00
bellard
7f1135b9a4 added stx_T1_A0 micro ops
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@508 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:28:06 +00:00
bellard
f68dd77007 fixed word bit operations with memory offset - suppressed push/pop micro operations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@507 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:27:42 +00:00
bellard
436d8b892a correct value for ADDSEG is real mode (fixes GRUB boot) - update static protected mode state - use generic tlb_set_page()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@506 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:26:31 +00:00
bellard
dc6f57fd55 debug updates - page_unprotect() is no longer needed in softmmu case
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@505 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:24:35 +00:00
bellard
65262d5738 added PE to static CPU state (avoids flushing translated code when swiching between protected and real mode) - moved memory defs to cpu-all.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@504 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:20:53 +00:00
bellard
773b93ee06 signal fix: update the host signal 'signal ignored' state to avoid unexpected -EINTR values (ash fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@503 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 17:15:59 +00:00
bellard
82c7e2a4c6 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@501 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 16:10:33 +00:00
bellard
546cdbd77d first multi target test (lauches 'ls')
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@500 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 16:08:39 +00:00
bellard
c265508067 more precise PIT gate emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@499 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 16:07:06 +00:00
bellard
dd4e27d810 removed test code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@498 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:58:16 +00:00
bellard
a41bc9af8f explicited S3 specific code - added more debug code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@497 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:55:00 +00:00
bellard
3bfd9da14f termios support for SPARC and PPC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@496 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:52:31 +00:00
bellard
c573ff6752 stat64 fix - added getpagesize()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@495 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:51:36 +00:00
bellard
060366c5ad SPARC fixes : syscall fixes - added user register window exception support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@494 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:50:01 +00:00
bellard
6da41eafc4 added CPU callbacks
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@493 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:48:38 +00:00
bellard
0124311e00 more generic TLB support - began to fix unlikely interrupt issues
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@492 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:48:17 +00:00
bellard
f515528907 aligned stack on 16 byte boundary - PPC target fixes - SPARC target fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@491 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:46:50 +00:00
bellard
b453b70bd8 sparc fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@490 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:45:21 +00:00
bellard
0ac4bd56a8 float access fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@489 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:44:17 +00:00
bellard
3811a291e2 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@488 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:27:57 +00:00
bellard
3415a4ddb4 invd and wbinvd support - fixed code gen logic for invlpg - simpler exception handling in load_seg()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@487 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:21:33 +00:00
bellard
b7f0f463a5 debug fixes - use more generic TLB mappings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@486 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:20:25 +00:00
bellard
8e682019e3 correct zero segment values when coming from VM86 mode - cache infos in CPUID - simpler exception handling in load_seg() - validate segments after lret/iret
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@485 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:18:37 +00:00
bellard
cf495bcf9f SPARC fixes: corrected PC/NPC logic (now slower but can be optimized a lot) - fixed flags computations - added register window exceptions support - fixed mul and div - added mulscc - fixed immediate field decoding
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@484 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 15:01:44 +00:00
bellard
fb0eaffc6d PowerPC fixes (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@483 c046a42c-6fe2-441c-8c8c-71466251a162
2004-01-04 14:57:11 +00:00
bellard
07ad1b93a3 disable keyboard interrupts if keyboard clock disabled (may not be fully correct) - added keyboard ID for extended keyboard
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@482 c046a42c-6fe2-441c-8c8c-71466251a162
2003-12-02 22:18:10 +00:00
bellard
d36cd60e6c P4 style multiplication eflags
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@481 c046a42c-6fe2-441c-8c8c-71466251a162
2003-12-02 22:01:31 +00:00
bellard
5e809a8095 dump irq inhibit flag as it is a part of the cpu state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@480 c046a42c-6fe2-441c-8c8c-71466251a162
2003-12-02 21:59:21 +00:00
bellard
791c2261d6 more complete eflags testing for multiplication (P4 case only)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@479 c046a42c-6fe2-441c-8c8c-71466251a162
2003-12-02 21:55:34 +00:00
bellard
163a7cb620 imull fix (suggested by Robert J. Harley)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@478 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-30 19:40:08 +00:00
bellard
6bb705711b a20 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@477 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-23 23:26:39 +00:00
bellard
4136f33c7e fixed eflags IF/IOPL update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@476 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-23 23:09:40 +00:00
bellard
6dca2016fc fixed PPC state reloading
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@475 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-23 17:32:06 +00:00
bellard
678673089d PowerPC target support (Jocelyn Mayer) - added better support for uid16
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@474 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-23 17:05:30 +00:00
bellard
28b6751f30 suppressed use of gen_multi - use intermediate FT0 register for floats - use T0 temporary for fpscr update - use PARAM1 for spr access - added untested single load/store support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@473 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-23 16:58:08 +00:00
bellard
79aceca54a PowerPC support (Jocelyn Mayer)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@472 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-23 14:55:54 +00:00
bellard
6a8c397deb FTST instruction fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@471 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-22 23:57:34 +00:00
bellard
9cdf757fd5 more fcmovxx tests
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@470 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-19 22:12:47 +00:00
bellard
36bdbe5479 fixed TB linking in case of code invalidation (fixes random segfaults)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@469 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-19 22:12:02 +00:00
bellard
8004340674 added fcmovxx support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@468 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-19 22:09:03 +00:00
bellard
a2cc3b2433 added fcmovxx support (fixes segfaults in some recent linux tools) - fixed irq inhibit logic : the irqs are inhibited only for one instruction after, even if the next one also inhibit irqs - stop translation after irq inhibition stops to give a chance to irqs (fixes install NT kernel startup)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@467 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-19 22:08:13 +00:00
bellard
afa05eb15e always completely redefine the TLB in case of MMU fault
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@466 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-19 22:04:21 +00:00
bellard
de5eaa6452 static config for SDL
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@465 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-16 23:18:17 +00:00
bellard
7517502475 fcmovx support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@464 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-16 20:18:52 +00:00
bellard
8f2b1fb008 more hack for CMOS interruption (enable linux /dev/rtc not to hang) - auto boot on cdrom if only device present
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@463 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-16 19:46:01 +00:00
bellard
891b38e446 more precise stack operations in call/int gates (16 bit wrapping is handled in all cases) - makes all call/int gates operations restartable in case of exception
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@462 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-16 16:06:03 +00:00
bellard
7dea1da4ae quick and dirty CMOS irq emulation (windows install uses it) - emm386 keyboard fix (need a better way...) - better serial emulation (windows install uses it) - LDT and TR caches init fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@461 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-16 15:59:30 +00:00
bellard
4ce900b44c make windows happier
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@460 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-16 15:46:05 +00:00
bellard
f3f2d9be03 call gate fix - verr and verw fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@459 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 23:15:36 +00:00
bellard
77729c2445 fixed pop %sp bug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@458 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 23:09:07 +00:00
bellard
d71b9a8b2f fixed lmsw instruction
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@457 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 02:48:18 +00:00
bellard
181f1558cd update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@456 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 01:47:16 +00:00
bellard
2750332396 Soundblaster 16 support (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@455 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 01:46:15 +00:00
bellard
f115e911d7 iret and int fix for vm86 - added undefined instructions for real and vm86 modes - added verr, verrw, arpl - added port io map
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@454 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 01:43:28 +00:00
bellard
3ab493de4c added verr, verw, arpl - more precise segment rights checks
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@453 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 01:42:19 +00:00
bellard
3e25f9515a io map checks
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@452 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-13 00:13:08 +00:00
bellard
246d897f4c dump more registers
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@451 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-12 23:55:40 +00:00
bellard
7e84c2498f full TSS support - IO map check support - conforming segment check fixes - iret in vm86 mode fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@450 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-12 23:39:19 +00:00
bellard
e670b89e3b added comments and TSS bit
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@449 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-12 23:23:42 +00:00
bellard
bd0d90b21d make Knoppix CD-ROM probe happy
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@448 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-12 22:23:01 +00:00
bellard
1a0636f8d7 new VGA bios
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@447 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-11 14:20:17 +00:00
bellard
2e134c9c55 64-bit multiplication fix (Ulrich Hecht)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@446 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-11 13:55:33 +00:00
bellard
5391d80669 moved IDE driver to ide.c
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@445 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-11 13:48:59 +00:00
bellard
36b486bb74 hardware level IDE CD-ROM emulation - added second IDE interface for up to 4 IDE disks emulation - added -boot command to enable CD boot
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@444 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-11 13:36:08 +00:00
bellard
4ad06a29b2 soft mmu fix (aka debian random seg fault fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@443 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-09 16:58:12 +00:00
bellard
e58143b355 ppc fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@442 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-09 14:42:54 +00:00
bellard
1f5476fcce a20 support - keyboard led fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@441 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-04 23:35:20 +00:00
bellard
461c0471af a20 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@440 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-04 23:34:23 +00:00
bellard
9c3ad57432 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@439 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-04 23:33:13 +00:00
bellard
e748ba4f53 ARM half word load/store fix (Ulrich Hecht)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@438 c046a42c-6fe2-441c-8c8c-71466251a162
2003-11-03 22:25:25 +00:00
bellard
b8ed223bfe big endian fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@437 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 22:10:22 +00:00
bellard
c970a162e7 temporary hack for PowerPC system emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@436 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:21:44 +00:00
bellard
c321f67309 enabled system emulator build on PowerPC - increased portability of soft mmu code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@435 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:18:42 +00:00
bellard
7f7f987341 endianness and portability fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@434 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:11:23 +00:00
bellard
aebcb60e55 no need for locks in system mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@433 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:08:17 +00:00
bellard
1a18c71b50 unused functions in system mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@432 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:07:51 +00:00
bellard
03a6c5103d cannot simply write segment registers in system mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@431 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:07:22 +00:00
bellard
128b346e0a cmov fix (bug on PowerPC)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@430 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 01:05:49 +00:00
bellard
415fa2ea77 soft MMU performance fix (oops)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@429 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-30 00:39:38 +00:00
bellard
9951bf39f9 fixed long double accesses when using soft MMU
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@428 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 23:06:17 +00:00
bellard
8948b5d613 fixed ldq() macros
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@427 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 23:04:30 +00:00
bellard
5086347239 CONFIG_STATIC patch
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@426 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 23:04:01 +00:00
bellard
9d4520d0e0 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@425 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 01:38:57 +00:00
bellard
5b9f457a89 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@424 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:49:54 +00:00
bellard
3a4739d651 static link
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@423 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:48:22 +00:00
bellard
76b62fd001 added binary archive
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@422 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:47:44 +00:00
bellard
b1f645758a redhat 9 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@421 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:47:19 +00:00
bellard
bc1b050d85 fixed distclean target
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@420 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:12:52 +00:00
bellard
03d5f74aee update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@419 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:09:43 +00:00
bellard
9f05cc34df fixed big endian ops
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@418 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-28 00:09:28 +00:00
bellard
285dc330bd update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@417 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 23:58:04 +00:00
bellard
baf8ebf01a fixed virtual memory access
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@416 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 23:57:40 +00:00
bellard
9d16dd550e make cpu test static
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@415 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 23:56:59 +00:00
bellard
78d6da976c license
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@414 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 23:55:20 +00:00
bellard
dd6ee15c37 fixed idt/gdt relocation bug - added support for Redhat kernels
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@413 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 23:36:59 +00:00
bellard
0db634747e qemu with softmmu is now the default executable
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@412 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:37:46 +00:00
bellard
6e59c1db89 full soft mmu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@411 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:24:54 +00:00
bellard
61382a500a full softmmu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@410 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:22:23 +00:00
bellard
3a51dee658 disabled signal hacks for softmmu version (qemu should be much more portable now...)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@409 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:18:35 +00:00
bellard
cc38b844d7 factorized debug code
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@408 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:16:14 +00:00
bellard
c6105c0a04 added correct memory access code for system emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@407 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:13:58 +00:00
bellard
93a40ea926 fixed mmu fault priviledge logic
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@406 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:13:06 +00:00
bellard
db8d746688 comments
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@405 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:12:17 +00:00
bellard
997344f303 added i386 user only target
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@404 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:10:39 +00:00
bellard
16e9b7de41 filename fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@403 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-27 21:09:52 +00:00
bellard
3486513433 log activation from gdb - gdb single step support for x86 - stop timer when cpu is being debugged
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@402 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-05 14:28:56 +00:00
bellard
0806e3f66f updated
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@401 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-01 00:15:32 +00:00
bellard
39b4da28b3 bios binary images
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@400 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-01 00:14:04 +00:00
bellard
5a67135a0b automatic man page generation - BIOS installation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@399 c046a42c-6fe2-441c-8c8c-71466251a162
2003-10-01 00:13:48 +00:00
bellard
42f1e0e49b tun-fd option support for external tundev config (Rusty Russell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@398 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 22:11:17 +00:00
bellard
27c3f2cb9b buffer overflow fix - handle case where stdin is closed (Rusty Russell)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@397 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:40:47 +00:00
bellard
a07cf92aed multiscan/doublescan fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@396 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:29:03 +00:00
bellard
01e3b763a6 removed SIGIOT
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@395 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:10:14 +00:00
bellard
0ae04d7367 allow Ctrl-C to be pressed when using gdb stub and SDL
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@394 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:09:16 +00:00
bellard
ebc054881f added utime syscall - fixed nanosleep exact behaviour
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@393 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:08:41 +00:00
bellard
a20dd508aa simplified invocation - added automatic IDE disk geometry guessing to reuse old disk images directly
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@392 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:07:02 +00:00
bellard
6180a1818a new directory structure
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@391 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 21:04:53 +00:00
bellard
d3eead2eec new directory structure
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@390 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 20:59:51 +00:00
bellard
853d6f7a83 sparc support - hack to fix case where real_host_page_size < TARGET_PAGE_SIZE (typically sparc target case)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@389 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 20:58:32 +00:00
bellard
93ac68bca5 sparc emulation target (thanx to Thomas M. Ogrisegg)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@388 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 20:57:29 +00:00
bellard
1e43adfc89 new directory structure - changed naming of qemu and vl
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@387 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 20:54:24 +00:00
bellard
7a3f194486 sparc emulation target (thanx to Thomas M. Ogrisegg)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@386 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 20:36:07 +00:00
bellard
2c0262afa7 new directory structure
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@385 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-30 20:34:21 +00:00
bellard
196ad10903 portable Linux test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@384 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-28 18:59:32 +00:00
bellard
b7dda06abf Redhat 9 fixes
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@383 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:57:56 +00:00
bellard
fcf8fcc8e5 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@382 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:56:56 +00:00
bellard
dbc5594cb6 finished simplifying string operations - correct TF flag handling for string operations and ss loading - simplified basic block exit code generation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@381 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:56:30 +00:00
bellard
4cbb86e1c4 added JUMP_TB2 for a third basic block exit jump point
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@380 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:53:29 +00:00
bellard
f513a41a3d finished simplifying string operations
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@379 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:52:47 +00:00
bellard
c106152d26 added two more jump points
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@378 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:51:45 +00:00
bellard
facc68be25 removed x86 hacks
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@377 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:51:18 +00:00
bellard
3ff0631ed9 added linux < 2.4.21 vm86 bug workaround - added extensive TF flag test
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@376 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-17 22:49:51 +00:00
bellard
b1ba65744e depth 32 fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@375 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-16 21:47:08 +00:00
bellard
b67d59594e glibc 2.3.x fix
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@374 c046a42c-6fe2-441c-8c8c-71466251a162
2003-09-16 21:46:04 +00:00
bellard
2e255c6b9f faster and more accurate segment handling
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@373 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-21 23:25:21 +00:00
bellard
3f33731662 pop ss, mov ss, x and sti disable irqs for the next instruction - began dispatch optimization by adding new x86 cpu 'hidden' flags
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@372 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-20 23:02:09 +00:00
bellard
d05e66d217 no error code if hardware interrupt
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@371 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-20 21:34:35 +00:00
bellard
2d80ae8987 avoid problems if make clean was not made before updating
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@370 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 23:01:33 +00:00
bellard
17383a2a2a gcc 3.x is mandatory now on PowerPC
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@369 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 22:28:58 +00:00
bellard
9257a9e49c workaround for gcc 3.3 bug or overoptimisation if a label is not used
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@368 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 22:21:18 +00:00
bellard
70a194b930 fixed invalid Linux asm/unistd.h header for PowerPC and gcc 3.3
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@367 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 22:20:16 +00:00
bellard
2573109866 pass function name to JMUP_TB()
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@366 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 22:19:11 +00:00
bellard
9dfa5b421d 64 bit fixes (Falk Hueffner)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@365 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 20:35:58 +00:00
bellard
9da8ba18e6 mode X double scan fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@364 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-11 20:33:04 +00:00
bellard
76bc683820 updated
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@363 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 23:41:46 +00:00
bellard
3b22c4707d fixed invalid ESP usage (Jon Nall)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@362 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 23:40:50 +00:00
bellard
96e6e05372 fixed invalid code gen
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@361 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 23:39:55 +00:00
bellard
e2222c3924 removed warnings
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@360 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 23:39:03 +00:00
bellard
31e8f3c894 PowerPC fix (Jon Nall)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@359 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 22:52:34 +00:00
bellard
9368caf64d updated
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@358 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 22:15:31 +00:00
bellard
38e584a072 m68k host port (Richard Zidlicky)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@357 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 22:14:22 +00:00
bellard
313aa56710 added VGA emulation - added PS/2 mouse and keyboard emulation - use SDL for VGA display
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@356 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:52:11 +00:00
bellard
4cbf74b6b8 soft mmu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@355 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:48:43 +00:00
bellard
33417e7025 soft mmu support - Memory I/O API - synthetize string instructions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@354 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:47:01 +00:00
bellard
4021dab059 soft mmu support - moved unrelated code to help2-i386.c - synthetize string instructions
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@353 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:41:46 +00:00
bellard
626df76abb build all targets at the same time
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@352 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:39:31 +00:00
bellard
abcd5da72e use bswap.h
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@351 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:38:48 +00:00
bellard
97a847bc03 build all targets at the same time - SDL probe support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@350 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:36:04 +00:00
bellard
ab93bbe2ae soft mmu support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@349 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-10 21:35:13 +00:00
bellard
0f0b726444 SDL support for VGA, keyboard and mouse
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@348 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-09 18:26:36 +00:00
bellard
b92e5a22ec Software MMU support (used for memory mapped devices such as VGA)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@347 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-08 23:58:05 +00:00
bellard
17b0018b42 Full VGA support, including old CGA modes, VGA planar and mode X
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@346 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-08 23:50:57 +00:00
bellard
39cf780327 fixed graphical VGA 16 color mode - fixed 9 pixel wide text mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@345 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-05 23:06:22 +00:00
bellard
e89f66eca9 Hardware level VGA emulation (only text mode is tested)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@344 c046a42c-6fe2-441c-8c8c-71466251a162
2003-08-04 23:30:47 +00:00
bellard
b6d78bfa0d correct CPL support (should fix flat real mode support)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@343 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-29 20:53:01 +00:00
bellard
c33a346edf first part of single stepping support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@342 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-29 20:50:33 +00:00
bellard
61a2ad53cb refresh clock dummy emulation (netbsd boot fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@341 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-27 22:19:00 +00:00
bellard
2c1794c42e more generic ljmp and lcall - fixed REPNZ usage for non compare string ops (FreeDos boot loader fix)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@340 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-27 21:11:27 +00:00
bellard
8a4c1cc411 fixed ss segment load - added ICEBP instruction
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@339 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 20:34:00 +00:00
bellard
330d0414a5 keyboard emulation - accepts to boot with Bochs BIOS and LGPL'ed VGA BIOS
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@338 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 18:11:40 +00:00
bellard
3802ce26a1 set to protected mode
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@337 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 18:02:28 +00:00
bellard
4abe615b84 removed debug
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@336 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 18:01:58 +00:00
bellard
a412ac572f real mode support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@335 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 18:01:40 +00:00
bellard
b2b5fb228f popw (%esp) test)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@334 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 18:00:58 +00:00
bellard
8f186479e2 real mode support (now boots from BOCHS BIOS and LGPL'ed VGA BIOS)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@333 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 17:59:00 +00:00
bellard
4c3a88a284 gdb stub breakpoints support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@332 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-26 12:06:08 +00:00
bellard
d6b4936796 update
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@331 c046a42c-6fe2-441c-8c8c-71466251a162
2003-07-13 22:37:44 +00:00
201 changed files with 81580 additions and 11120 deletions

15
.cvsignore Normal file
View File

@@ -0,0 +1,15 @@
arm-user
config-host.*
dyngen
i386
i386-softmmu
i386-user
ppc-softmmu
ppc-user
qemu-doc.html
qemu-mkcow
qemu-tech.html
qemu.1
qemu.pod
sparc-user
vmdk2raw

139
Changelog
View File

@@ -1,3 +1,142 @@
version 0.6.0:
- minimalist FPU exception support (NetBSD FPU probe fix)
- cr0.ET fix (Win95 boot)
- *BSD port (Markus Niemisto)
- I/O access fix (signaled by Mark Jonckheere)
- IDE drives serial number fix (Mike Nordell)
- int13 CDROM BIOS fix (aka Solaris x86 install CD fix)
- int15, ah=86 BIOS fix (aka Solaris x86 hardware probe hang up fix)
- BSR/BSF "undefined behaviour" fix
- vmdk2raw: convert VMware disk images to raw images
- PCI support
- NE2K PCI support
- dummy VGA PCI support
- VGA font selection fix (Daniel Serpell)
- PIC reset fix (Hidemi KAWAI)
- PIC spurious irq support (aka Solaris install bug)
- added '-localtime' option
- Cirrus CL-GD54xx VGA support (initial patch by Makoto Suzuki (suzu))
- APM and system shutdown support
- Fixed system reset
- Support for other PC BIOSes
- Initial PowerMac hardware emulation
- PowerMac/PREP OpenFirmware compatible BIOS (Jocelyn Mayer)
- initial IDE BMDMA support (needed for Darwin x86)
- Set the default memory size for PC emulation to 128 MB
version 0.5.5:
- SDL full screen support (initial patch by malc)
- VGA support on PowerPC PREP
- VBE fixes (Matthew Mastracci)
- PIT fixes (aka Win98 hardware probe and "VGA slowness" bug)
- IDE master only fixes (aka Win98 CD-ROM probe bug)
- ARM load/store half word fix (Ulrich Hecht)
- FDC fixes for Win98
version 0.5.4:
- qemu-fast fixes
- BIOS area protection fix (aka EMM386.EXE fix) (Mike Nordell)
- keyboard/mouse fix (Mike Nordell)
- IDE fixes (Linux did not recognized slave drivers)
- VM86 EIP masking fix (aka NT5 install fix) (Mike Nordell)
- QEMU can now boot a PowerPC Linux kernel (Jocelyn Mayer)
- User mode network stack
- imul imm8 fix + 0x82 opcode support (Hidemi KAWAI)
- precise self modifying code (aka BeOS install bug)
version 0.5.3:
- added Bochs VESA VBE support
- VGA memory map mode 3 access fix (OS/2 install fix)
- IDE fixes (Jens Axboe)
- CPU interrupt fixes
- fixed various TLB invalidation cases (NT install)
- fixed cr0.WP semantics (XP install)
- direct chaining support for SPARC and PowerPC (faster)
- ARM NWFPE support (initial patch by Ulrich Hecht)
- added specific x86 to x86 translator (close to native performance
in qemu-i386 and qemu-fast)
- shm syscalls support (Paul McKerras)
- added accurate CR0.MP/ME/TS emulation
- fixed DMA memory write access (Win95 boot floppy fix)
- graphical x86 linux loader
- command line monitor
- generic removable device support
- support of CD-ROM change
- multiple network interface support
- initial x86-64 host support (Gwenole Beauchesne)
- lret to outer priviledge fix (OS/2 install fix)
- task switch fixes (SkyOS boot)
- VM save/restore commands
- new timer API
- more precise RTC emulation (periodic timers + time updates)
- Win32 port (initial patch by Kazu)
version 0.5.2:
- improved soft MMU speed (assembly functions and specializing)
- improved multitasking speed by avoiding flushing TBs when
switching tasks
- improved qemu-fast speed
- improved self modifying code handling (big performance gain in
softmmu mode).
- fixed IO checking
- fixed CD-ROM detection (win98 install CD)
- fixed addseg real mode bug (GRUB boot fix)
- added ROM memory support (win98 boot)
- fixed 'call Ev' in case of paging exception
- updated the script 'qemu-binfmt-conf.sh' to use QEMU automagically
when launching executables for the supported target CPUs.
- PowerPC system emulation update (Jocelyn Mayer)
- PC floppy emulation and DMA fixes (Jocelyn Mayer)
- polled mode for PIC (Jocelyn Mayer)
- fixed PTE dirty bit handling
- fixed xadd same reg bug
- fixed cmpxchg exception safeness
- access to virtual memory in gdb stub
- task gate and NT flag fixes
- eflags optimisation fix for string operations
version 0.5.1:
- float access fixes when using soft mmu
- PC emulation support on PowerPC
- A20 support
- IDE CD-ROM emulation
- ARM fixes (Ulrich Hecht)
- SB16 emulation (malc)
- IRET and INT fixes in VM86 mode with IOPL=3
- Port I/Os use TSS io map
- Full task switching/task gate support
- added verr, verw, arpl, fcmovxx
- PowerPC target support (Jocelyn Mayer)
- Major SPARC target fixes (dynamically linked programs begin to work)
version 0.5.0:
- full hardware level VGA emulation
- graphical display with SDL
- added PS/2 mouse and keyboard emulation
- popw (%esp) fix
- mov to/from segment data width fix
- added real mode support
- added Bochs BIOS and LGPL'ed VGA BIOS loader in qemu
- m68k host port (Richard Zidlicky)
- partial soft MMU support for memory mapped I/Os
- multi-target build
- fixed: no error code in hardware interrupts
- fixed: pop ss, mov ss, x and sti disable hardware irqs for the next insn
- correct single stepping thru string operations
- preliminary SPARC target support (Thomas M. Ogrisegg)
- tun-fd option (Rusty Russell)
- automatic IDE geometry detection
- renamed 'vl' to qemu[-fast] and user qemu to qemu-{cpu}.
- added man page
- added full soft mmu mode to launch unpatched OSes.
version 0.4.3:
- x86 exception fix in case of nop instruction.

296
Makefile
View File

@@ -1,255 +1,113 @@
include config.mak
include config-host.mak
CFLAGS=-Wall -O2 -g
ifdef CONFIG_DARWIN
CFLAGS+= -mdynamic-no-pic
endif
ifdef CONFIG_WIN32
CFLAGS+=-fpack-struct
endif
LDFLAGS=-g
LIBS=
DEFINES=-DHAVE_BYTESWAP_H
HELPER_CFLAGS=$(CFLAGS)
PROGS=qemu
DEFINES+=-D_GNU_SOURCE
ifndef CONFIG_WIN32
TOOLS=qemu-mkcow vmdk2raw
endif
ifdef CONFIG_STATIC
LDFLAGS+=-static
endif
ifeq ($(ARCH),i386)
CFLAGS+=-fomit-frame-pointer
OP_CFLAGS=$(CFLAGS) -mpreferred-stack-boundary=2
ifeq ($(HAVE_GCC3_OPTIONS),yes)
OP_CFLAGS+= -falign-functions=0
else
OP_CFLAGS+= -malign-functions=0
endif
ifdef TARGET_GPROF
LDFLAGS+=-Wl,-T,i386.ld
else
# 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
endif
ifeq ($(TARGET_ARCH), i386)
PROGS+=vl vlmkcow
endif
endif
all: dyngen$(EXESUF) $(TOOLS) qemu-doc.html qemu-tech.html qemu.1
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
done
ifeq ($(ARCH),ppc)
OP_CFLAGS=$(CFLAGS)
LDFLAGS+=-Wl,-T,ppc.ld
endif
qemu-mkcow: qemu-mkcow.c
$(CC) $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ $(LIBS)
ifeq ($(ARCH),s390)
OP_CFLAGS=$(CFLAGS)
LDFLAGS+=-Wl,-T,s390.ld
endif
vmdk2raw: vmdk2raw.c
$(CC) $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ $(LIBS)
ifeq ($(ARCH),sparc)
CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
LDFLAGS+=-m32
OP_CFLAGS=$(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,sparc.ld -static
endif
ifeq ($(ARCH),sparc64)
CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
LDFLAGS+=-m64
OP_CFLAGS=$(CFLAGS) -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
# Ensure there's only a single GP
CFLAGS += -msmall-data
LDFLAGS+=-Wl,-T,alpha.ld
endif
ifeq ($(ARCH),ia64)
OP_CFLAGS=$(CFLAGS)
endif
ifeq ($(ARCH),arm)
OP_CFLAGS=$(CFLAGS) -mno-sched-prolog
LDFLAGS+=-Wl,-T,arm.ld
endif
ifeq ($(HAVE_GCC3_OPTIONS),yes)
# very important to generate a return at the end of every operation
OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls
endif
#########################################################
DEFINES+=-D_GNU_SOURCE
LIBS+=-lm
# profiling code
ifdef TARGET_GPROF
LDFLAGS+=-p
main.o: CFLAGS+=-p
endif
OBJS= elfload.o main.o syscall.o mmap.o signal.o path.o
ifeq ($(TARGET_ARCH), i386)
OBJS+= vm86.o
endif
SRCS:= $(OBJS:.o=.c)
OBJS+= libqemu.a
# cpu emulator library
LIBOBJS=thunk.o exec.o translate.o cpu-exec.o gdbstub.o
ifeq ($(TARGET_ARCH), i386)
LIBOBJS+=translate-i386.o op-i386.o helper-i386.o
endif
ifeq ($(TARGET_ARCH), arm)
LIBOBJS+=translate-arm.o op-arm.o
endif
# NOTE: the disassembler code is only needed for debugging
LIBOBJS+=disas.o
ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
LIBOBJS+=i386-dis.o
endif
ifeq ($(findstring alpha, $(TARGET_ARCH) $(ARCH)),alpha)
LIBOBJS+=alpha-dis.o
endif
ifeq ($(findstring ppc, $(TARGET_ARCH) $(ARCH)),ppc)
LIBOBJS+=ppc-dis.o
endif
ifeq ($(findstring sparc, $(TARGET_ARCH) $(ARCH)),sparc)
LIBOBJS+=sparc-dis.o
endif
ifeq ($(findstring arm, $(TARGET_ARCH) $(ARCH)),arm)
LIBOBJS+=arm-dis.o
endif
ifeq ($(ARCH),ia64)
OBJS += ia64-syscall.o
endif
all: $(PROGS) qemu-doc.html
qemu: $(OBJS)
$(CC) $(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)
echo -ne '\001\000\000\000' | dd of=qemu bs=1 seek=48 count=4 conv=notrunc
endif
# must use static linking to avoid leaving stuff in virtual address space
vl: vl.o block.o libqemu.a
$(CC) -static -Wl,-T,i386-vl.ld -o $@ $^ $(LIBS)
vlmkcow: vlmkcow.o
$(CC) -o $@ $^ $(LIBS)
depend: $(SRCS)
$(CC) -MM $(CFLAGS) $^ 1>.depend
# libqemu
libqemu.a: $(LIBOBJS)
rm -f $@
$(AR) rcs $@ $(LIBOBJS)
dyngen: dyngen.c
$(HOST_CC) -O2 -Wall -g $< -o $@
translate-$(TARGET_ARCH).o: translate-$(TARGET_ARCH).c gen-op-$(TARGET_ARCH).h opc-$(TARGET_ARCH).h cpu-$(TARGET_ARCH).h
translate.o: translate.c op-$(TARGET_ARCH).h opc-$(TARGET_ARCH).h cpu-$(TARGET_ARCH).h
op-$(TARGET_ARCH).h: op-$(TARGET_ARCH).o dyngen
./dyngen -o $@ $<
opc-$(TARGET_ARCH).h: op-$(TARGET_ARCH).o dyngen
./dyngen -c -o $@ $<
gen-op-$(TARGET_ARCH).h: op-$(TARGET_ARCH).o dyngen
./dyngen -g -o $@ $<
op-$(TARGET_ARCH).o: op-$(TARGET_ARCH).c
$(CC) $(OP_CFLAGS) $(DEFINES) -c -o $@ $<
helper-$(TARGET_ARCH).o: helper-$(TARGET_ARCH).c
$(CC) $(HELPER_CFLAGS) $(DEFINES) -c -o $@ $<
op-i386.o: op-i386.c opreg_template.h ops_template.h ops_template_mem.h
op-arm.o: op-arm.c op-arm-template.h
%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
dyngen$(EXESUF): dyngen.c
$(HOST_CC) $(CFLAGS) $(DEFINES) -o $@ $^
clean:
# avoid old build problems by removing potentially incorrect old files
rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS qemu.pod
$(MAKE) -C tests clean
rm -f *.o *.a *~ qemu dyngen TAGS
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
done
distclean: clean
rm -f config.mak config.h
rm -f config-host.mak config-host.h
for d in $(TARGET_DIRS); do \
rm -rf $$d || exit 1 ; \
done
install: $(PROGS)
mkdir -p $(prefix)/bin
install -m 755 -s $(PROGS) $(prefix)/bin
install: all
mkdir -p "$(bindir)"
ifndef CONFIG_WIN32
install -m 755 -s $(TOOLS) "$(bindir)"
endif
mkdir -p "$(datadir)"
install -m 644 pc-bios/bios.bin pc-bios/vgabios.bin \
pc-bios/vgabios-cirrus.bin \
pc-bios/ppc_rom.bin \
pc-bios/linux_boot.bin "$(datadir)"
mkdir -p "$(docdir)"
install -m 644 qemu-doc.html qemu-tech.html "$(docdir)"
ifndef CONFIG_WIN32
mkdir -p "$(mandir)/man1"
install qemu.1 qemu-mkcow.1 "$(mandir)/man1"
endif
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
done
# various test targets
test speed: qemu
make -C tests $@
test speed test2: all
$(MAKE) -C tests $@
TAGS:
etags *.[ch] tests/*.[ch]
# documentation
qemu-doc.html: qemu-doc.texi
%.html: %.texi
texi2html -monolithic -number $<
FILES= \
README README.distrib COPYING COPYING.LIB TODO Changelog VERSION \
configure \
dyngen.c dyngen.h dyngen-exec.h ioctls.h syscall_types.h \
Makefile elf.h elfload.c main.c signal.c qemu.h \
syscall.c syscall_defs.h vm86.c path.c mmap.c \
i386.ld ppc.ld alpha.ld s390.ld sparc.ld arm.ld\
vl.c i386-vl.ld vl.h block.c vlmkcow.c\
thunk.c cpu-exec.c translate.c cpu-all.h thunk.h exec.h\
exec.c cpu-exec.c gdbstub.c\
cpu-i386.h op-i386.c helper-i386.c syscall-i386.h translate-i386.c \
exec-i386.h ops_template.h ops_template_mem.h op_string.h opreg_template.h \
cpu-arm.h syscall-arm.h exec-arm.h op-arm.c translate-arm.c op-arm-template.h \
dis-asm.h disas.c disas.h alpha-dis.c ppc-dis.c i386-dis.c sparc-dis.c \
arm-dis.c \
tests/Makefile \
tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h \
tests/test-i386-muldiv.h tests/test-i386-code16.S tests/test-i386-vm86.S \
tests/hello-i386.c tests/hello-i386 \
tests/hello-arm.c tests/hello-arm \
tests/sha1.c \
tests/testsig.c tests/testclone.c tests/testthread.c \
tests/runcom.c tests/pi_10.com \
tests/test_path.c \
qemu-doc.texi qemu-doc.html
qemu.1: qemu-doc.texi
./texi2pod.pl $< qemu.pod
pod2man --section=1 --center=" " --release=" " qemu.pod > $@
FILE=qemu-$(VERSION)
FILE=qemu-$(shell cat VERSION)
# tar release (use 'make -k tar' on a checkouted tree)
tar:
rm -rf /tmp/$(FILE)
mkdir -p /tmp/$(FILE)
cp -P $(FILES) /tmp/$(FILE)
( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) )
cp -r . /tmp/$(FILE)
( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) --exclude CVS )
rm -rf /tmp/$(FILE)
# generate a binary distribution including the test binary environnment
BINPATH=/usr/local/qemu-i386
# generate a binary distribution
tarbin:
tar zcvf /tmp/qemu-$(VERSION)-i386-glibc21.tar.gz \
$(BINPATH)/etc $(BINPATH)/lib $(BINPATH)/bin $(BINPATH)/usr
tar zcvf /tmp/qemu-$(VERSION)-i386-wine.tar.gz \
$(BINPATH)/wine
( cd / ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \
$(bindir)/qemu $(bindir)/qemu-fast \
$(bindir)/qemu-system-ppc \
$(bindir)/qemu-i386 \
$(bindir)/qemu-arm \
$(bindir)/qemu-sparc \
$(bindir)/qemu-ppc \
$(bindir)/qemu-mkcow $(bindir)/vmdk2raw \
$(datadir)/bios.bin \
$(datadir)/vgabios.bin \
$(datadir)/vgabios-cirrus.bin \
$(datadir)/ppc_rom.bin \
$(datadir)/linux_boot.bin \
$(docdir)/qemu-doc.html \
$(docdir)/qemu-tech.html \
$(mandir)/man1/qemu.1 $(mandir)/man1/qemu-mkcow.1 )
ifneq ($(wildcard .depend),)
include .depend

348
Makefile.target Normal file
View File

@@ -0,0 +1,348 @@
include config.mak
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_ARCH)
VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw
DEFINES=-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)
endif
CFLAGS=-Wall -O2 -g -fno-strict-aliasing
LDFLAGS=-g
LIBS=
HELPER_CFLAGS=$(CFLAGS)
DYNGEN=../dyngen$(EXESUF)
# user emulator name
QEMU_USER=qemu-$(TARGET_ARCH)
# system emulator name
ifdef CONFIG_SOFTMMU
ifeq ($(TARGET_ARCH), i386)
QEMU_SYSTEM=qemu$(EXESUF)
else
QEMU_SYSTEM=qemu-system-$(TARGET_ARCH)$(EXESUF)
endif
else
QEMU_SYSTEM=qemu-fast
endif
ifdef CONFIG_USER_ONLY
PROGS=$(QEMU_USER)
else
ifeq ($(TARGET_ARCH), i386)
ifeq ($(ARCH), i386)
PROGS+=$(QEMU_SYSTEM)
ifndef CONFIG_SOFTMMU
CONFIG_STATIC=y
endif
else
# the system emulator using soft mmu is portable
ifdef CONFIG_SOFTMMU
PROGS+=$(QEMU_SYSTEM)
endif
endif # ARCH != i386
endif # TARGET_ARCH = i386
ifeq ($(TARGET_ARCH), ppc)
ifeq ($(ARCH), ppc)
PROGS+=$(QEMU_SYSTEM)
endif
ifeq ($(ARCH), i386)
ifdef CONFIG_SOFTMMU
PROGS+=$(QEMU_SYSTEM)
endif
endif # ARCH = i386
ifeq ($(ARCH), amd64)
ifdef CONFIG_SOFTMMU
PROGS+=$(QEMU_SYSTEM)
endif
endif # ARCH = amd64
endif # TARGET_ARCH = ppc
endif # !CONFIG_USER_ONLY
ifdef CONFIG_STATIC
LDFLAGS+=-static
endif
ifeq ($(ARCH),i386)
CFLAGS+=-fomit-frame-pointer
OP_CFLAGS=$(CFLAGS) -mpreferred-stack-boundary=2
ifeq ($(HAVE_GCC3_OPTIONS),yes)
OP_CFLAGS+= -falign-functions=0
else
OP_CFLAGS+= -malign-functions=0
endif
ifdef TARGET_GPROF
USE_I386_LD=y
endif
ifdef CONFIG_STATIC
USE_I386_LD=y
endif
ifdef USE_I386_LD
LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386.ld
else
# 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
endif
endif
ifeq ($(ARCH),amd64)
OP_CFLAGS=$(CFLAGS) -falign-functions=0
LDFLAGS+=-Wl,-T,$(SRC_PATH)/amd64.ld
endif
ifeq ($(ARCH),ppc)
CFLAGS+= -D__powerpc__
OP_CFLAGS=$(CFLAGS)
LDFLAGS+=-Wl,-T,$(SRC_PATH)/ppc.ld
endif
ifeq ($(ARCH),s390)
OP_CFLAGS=$(CFLAGS)
LDFLAGS+=-Wl,-T,$(SRC_PATH)/s390.ld
endif
ifeq ($(ARCH),sparc)
CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
LDFLAGS+=-m32
OP_CFLAGS=$(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
endif
ifeq ($(ARCH),sparc64)
CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
LDFLAGS+=-m64
OP_CFLAGS=$(CFLAGS) -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
# Ensure there's only a single GP
CFLAGS += -msmall-data
LDFLAGS+=-Wl,-T,$(SRC_PATH)/alpha.ld
endif
ifeq ($(ARCH),ia64)
OP_CFLAGS=$(CFLAGS)
endif
ifeq ($(ARCH),arm)
OP_CFLAGS=$(CFLAGS) -mno-sched-prolog
LDFLAGS+=-Wl,-T,$(SRC_PATH)/arm.ld
endif
ifeq ($(ARCH),m68k)
OP_CFLAGS=$(CFLAGS) -fomit-frame-pointer
LDFLAGS+=-Wl,-T,m68k.ld
endif
ifeq ($(HAVE_GCC3_OPTIONS),yes)
# very important to generate a return at the end of every operation
OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls
endif
ifeq ($(CONFIG_DARWIN),yes)
OP_CFLAGS+= -mdynamic-no-pic
endif
#########################################################
DEFINES+=-D_GNU_SOURCE
LIBS+=-lm
ifdef CONFIG_WIN32
LIBS+=-lwinmm
endif
# profiling code
ifdef TARGET_GPROF
LDFLAGS+=-p
main.o: CFLAGS+=-p
endif
OBJS= elfload.o main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o
ifeq ($(TARGET_ARCH), i386)
OBJS+= vm86.o
endif
ifeq ($(TARGET_ARCH), arm)
OBJS+=nwfpe/softfloat.o 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
endif
SRCS:= $(OBJS:.o=.c)
OBJS+= libqemu.a
# cpu emulator library
LIBOBJS=exec.o translate-all.o cpu-exec.o\
translate.o op.o
ifeq ($(TARGET_ARCH), i386)
LIBOBJS+=helper.o helper2.o
ifeq ($(ARCH), i386)
LIBOBJS+=translate-copy.o
endif
endif
ifeq ($(TARGET_ARCH), ppc)
LIBOBJS+= op_helper.o helper.o
endif
# NOTE: the disassembler code is only needed for debugging
LIBOBJS+=disas.o
ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
USE_I386_DIS=y
endif
ifeq ($(findstring amd64, $(TARGET_ARCH) $(ARCH)),amd64)
USE_I386_DIS=y
endif
ifdef USE_I386_DIS
LIBOBJS+=i386-dis.o
endif
ifeq ($(findstring alpha, $(TARGET_ARCH) $(ARCH)),alpha)
LIBOBJS+=alpha-dis.o
endif
ifeq ($(findstring ppc, $(TARGET_ARCH) $(ARCH)),ppc)
LIBOBJS+=ppc-dis.o
endif
ifeq ($(findstring sparc, $(TARGET_ARCH) $(ARCH)),sparc)
LIBOBJS+=sparc-dis.o
endif
ifeq ($(findstring arm, $(TARGET_ARCH) $(ARCH)),arm)
LIBOBJS+=arm-dis.o
endif
ifeq ($(ARCH),ia64)
OBJS += ia64-syscall.o
endif
all: $(PROGS)
$(QEMU_USER): $(OBJS)
$(CC) $(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)
echo -ne '\001\000\000\000' | dd of=qemu bs=1 seek=48 count=4 conv=notrunc
endif
# must use static linking to avoid leaving stuff in virtual address space
VL_OBJS=vl.o osdep.o block.o monitor.o pci.o
ifeq ($(TARGET_ARCH), i386)
# Hardware support
VL_OBJS+= ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
VL_OBJS+= cirrus_vga.o
endif
ifeq ($(TARGET_ARCH), ppc)
VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o sb16.o dma.o oss.o
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
endif
ifdef CONFIG_GDBSTUB
VL_OBJS+=gdbstub.o
endif
ifdef CONFIG_SDL
VL_OBJS+=sdl.o
endif
ifdef CONFIG_SLIRP
DEFINES+=-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
VL_OBJS+=$(addprefix slirp/, $(SLIRP_OBJS))
endif
VL_LDFLAGS=
# specific flags are needed for non soft mmu emulator
ifdef CONFIG_STATIC
VL_LDFLAGS+=-static
endif
ifndef CONFIG_SOFTMMU
VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386-vl.ld
endif
ifndef CONFIG_DARWIN
ifndef CONFIG_WIN32
VL_LIBS=-lutil
endif
endif
$(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(VL_LIBS)
sdl.o: sdl.c
$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
depend: $(SRCS)
$(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
# libqemu
libqemu.a: $(LIBOBJS)
rm -f $@
$(AR) rcs $@ $(LIBOBJS)
translate.o: translate.c gen-op.h opc.h cpu.h
translate-all.o: translate-all.c op.h opc.h cpu.h
op.h: op.o $(DYNGEN)
$(DYNGEN) -o $@ $<
opc.h: op.o $(DYNGEN)
$(DYNGEN) -c -o $@ $<
gen-op.h: op.o $(DYNGEN)
$(DYNGEN) -g -o $@ $<
op.o: op.c
$(CC) $(OP_CFLAGS) $(DEFINES) -c -o $@ $<
helper.o: helper.c
$(CC) $(HELPER_CFLAGS) $(DEFINES) -c -o $@ $<
ifeq ($(TARGET_ARCH), i386)
op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h
endif
ifeq ($(TARGET_ARCH), arm)
op.o: op.c op_template.h
endif
ifeq ($(TARGET_ARCH), sparc)
op.o: op.c op_template.h
endif
ifeq ($(TARGET_ARCH), ppc)
op.o: op.c op_template.h op_mem.h
op_helper.o: op_helper_mem.h
endif
%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
%.o: %.S
$(CC) $(DEFINES) -c -o $@ $<
clean:
rm -f *.o *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o
install: all
ifneq ($(PROGS),)
install -m 755 -s $(PROGS) "$(bindir)"
endif
ifneq ($(wildcard .depend),)
include .depend
endif

32
README
View File

@@ -6,35 +6,17 @@ INSTALLATION
Type
./configure --interp-prefix=/usr/local/qemu-i386
./configure
make
to build qemu and libqemu.a.
to build qemu, qemu-CPU and libqemu.a (CPU is the name of the various
supported target CPUs).
Type
make install
to install QEMU in /usr/local/bin
* On x86 you should be able to launch any program by using the
libraries installed on your PC. For example:
./qemu -L / /bin/ls
* On non x86 CPUs, you need first to download at least an x86 glibc
(qemu-XXX-i386-glibc21.tar.gz on the qemu web page). Ensure that
LD_LIBRARY_PATH is not set:
unset LD_LIBRARY_PATH
Then you can launch the precompiled 'ls' x86 executable:
./qemu /usr/local/qemu-i386/bin/ls-i386
You can look at /usr/local/qemu-i386/bin/qemu-conf.sh so that QEMU is
automatically launched by the Linux kernel when you try to launch x86
executables.
to install QEMU in /usr/local
Tested tool versions
--------------------
@@ -52,7 +34,8 @@ x86 2.95.2 2.13.2 2.1.3 2.4.18
2.96 2.11.93.0.2 2.2.5 2.4.18 Red Hat 7.3
3.2.2 2.13.90.0.18 2.3.2 2.4.20 Red Hat 9
PowerPC 2.95.4 2.12.90.0.1 2.2.5 2.4.20-pre2 Debian 3.0
PowerPC 3.3 [4] 2.13.90.0.18 2.3.1 2.4.20briq
3.2
Alpha 3.3 [1] 2.14.90.0.4 2.2.5 2.2.20 [2] Debian 3.0
@@ -66,6 +49,9 @@ ARM 2.95.4 2.12.90.0.1 2.2.5 2.4.9 [3] Debian 3.0
(untested).
[3] 2.4.9-ac10-rmk2-np1-cerf2
[4] gcc 2.95.x generates invalid code when using too many register
variables. You must use gcc 3.x on PowerPC.
Documentation
-------------

View File

@@ -6,11 +6,11 @@ x86 binary distribution:
* wine-20020411 tarball
./configure --prefix=/usr/local/qemu-i386/wine
./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 /usr/local/qemu-i386/bin/ldconfig-i386 -C /usr/local/qemu-i386/etc/ld.so.cache
qemu-i386 /usr/gnemul/qemu-i386/bin/ldconfig-i386 -C /usr/gnemul/qemu-i386/etc/ld.so.cache

30
TODO
View File

@@ -1,17 +1,35 @@
- optimize FPU operations (evaluate x87 stack pointer statically) and
fix cr0.TS emulation
short term:
----------
- physical memory cache (reduce qemu-fast address space size to about 32 MB)
- better code fetch (different exception handling + CS.limit support)
- do not resize vga if invalid size.
- avoid looping if only exceptions
- handle fast timers + add explicit clocks
- cycle counter for all archs
- TLB code protection support for PPC
- add sysenter/sysexit and fxsr for L4 pistachio 686
- basic VGA optimizations
- disable SMC handling for ARM/SPARC/PPC (not finished)
- see undefined flags for BTx insn
- user/kernel PUSHL/POPL in helper.c
- keyboard output buffer filling timing emulation
- return UD exception if LOCK prefix incorrectly used
- test ldt limit < 7 ?
- tests for each target CPU
- fix CCOP optimisation
- fix all remaining thread lock issues (must put TBs in a specific invalid
state, find a solution for tb_flush()).
- cpu loop optimisation (optimise ret case as the cpu state does not change)
- fix arm fpu rounding (at least for float->integer conversions)
- add IPC syscalls
- SMP support
lower priority:
--------------
- HDD geometry in CMOS (not used except for very old DOS programs)
- suppress shift_mem ops
- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret)
- sysenter/sysexit emulation
- SMP support
- finish segment ops (call far, ret far, load_seg suppressed)
- optimize FPU operations (evaluate x87 stack pointer statically)
- add IPC syscalls
- use -msoft-float on ARM
- use kernel traps for unaligned accesses on ARM ?
- handle rare page fault cases (in particular if page fault in heplers or

View File

@@ -1 +1 @@
0.4.3
0.6.0

431
a.out.h Normal file
View File

@@ -0,0 +1,431 @@
/* a.out.h
Copyright 1997, 1998, 1999, 2001 Red Hat, Inc.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef _A_OUT_H_
#define _A_OUT_H_
#ifdef __cplusplus
extern "C" {
#endif
#define COFF_IMAGE_WITH_PE
#define COFF_LONG_SECTION_NAMES
/*** coff information for Intel 386/486. */
/********************** FILE HEADER **********************/
struct external_filehdr {
short f_magic; /* magic number */
short f_nscns; /* number of sections */
unsigned long f_timdat; /* time & date stamp */
unsigned long f_symptr; /* file pointer to symtab */
unsigned long f_nsyms; /* number of symtab entries */
short f_opthdr; /* sizeof(optional hdr) */
short f_flags; /* flags */
};
/* Bits for f_flags:
* F_RELFLG relocation info stripped from file
* F_EXEC file is executable (no unresolved external references)
* F_LNNO line numbers stripped from file
* F_LSYMS local symbols stripped from file
* F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax)
*/
#define F_RELFLG (0x0001)
#define F_EXEC (0x0002)
#define F_LNNO (0x0004)
#define F_LSYMS (0x0008)
#define I386MAGIC 0x14c
#define I386PTXMAGIC 0x154
#define I386AIXMAGIC 0x175
/* This is Lynx's all-platform magic number for executables. */
#define LYNXCOFFMAGIC 0415
#define I386BADMAG(x) (((x).f_magic != I386MAGIC) \
&& (x).f_magic != I386AIXMAGIC \
&& (x).f_magic != I386PTXMAGIC \
&& (x).f_magic != LYNXCOFFMAGIC)
#define FILHDR struct external_filehdr
#define FILHSZ 20
/********************** AOUT "OPTIONAL HEADER"=
**********************/
typedef struct
{
unsigned short magic; /* type of file */
unsigned short vstamp; /* version stamp */
unsigned long tsize; /* text size in bytes, padded to FW bdry*/
unsigned long dsize; /* initialized data " " */
unsigned long bsize; /* uninitialized data " " */
unsigned long entry; /* entry pt. */
unsigned long text_start; /* base of text used for this file */
unsigned long data_start; /* base of data used for this file=
*/
}
AOUTHDR;
#define AOUTSZ 28
#define AOUTHDRSZ 28
#define OMAGIC 0404 /* object files, eg as output */
#define ZMAGIC 0413 /* demand load format, eg normal ld output */
#define STMAGIC 0401 /* target shlib */
#define SHMAGIC 0443 /* host shlib */
/* define some NT default values */
/* #define NT_IMAGE_BASE 0x400000 moved to internal.h */
#define NT_SECTION_ALIGNMENT 0x1000
#define NT_FILE_ALIGNMENT 0x200
#define NT_DEF_RESERVE 0x100000
#define NT_DEF_COMMIT 0x1000
/********************** SECTION HEADER **********************/
struct external_scnhdr {
char s_name[8]; /* section name */
unsigned long s_paddr; /* physical address, offset
of last addr in scn */
unsigned long s_vaddr; /* virtual address */
unsigned long s_size; /* section size */
unsigned long s_scnptr; /* file ptr to raw data for section */
unsigned long s_relptr; /* file ptr to relocation */
unsigned long s_lnnoptr; /* file ptr to line numbers */
unsigned short s_nreloc; /* number of relocation entries */
unsigned short s_nlnno; /* number of line number entries*/
unsigned long s_flags; /* flags */
};
#define SCNHDR struct external_scnhdr
#define SCNHSZ 40
/*
* names of "special" sections
*/
#define _TEXT ".text"
#define _DATA ".data"
#define _BSS ".bss"
#define _COMMENT ".comment"
#define _LIB ".lib"
/********************** LINE NUMBERS **********************/
/* 1 line number entry for every "breakpointable" source line in a section.
* Line numbers are grouped on a per function basis; first entry in a function
* grouping will have l_lnno = 0 and in place of physical address will be the
* symbol table index of the function name.
*/
struct external_lineno {
union {
unsigned long l_symndx; /* function name symbol index, iff l_lnno 0 */
unsigned long l_paddr; /* (physical) address of line number */
} l_addr;
unsigned short l_lnno; /* line number */
};
#define LINENO struct external_lineno
#define LINESZ 6
/********************** SYMBOLS **********************/
#define E_SYMNMLEN 8 /* # characters in a symbol name */
#define E_FILNMLEN 14 /* # characters in a file name */
#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
struct external_syment
{
union {
char e_name[E_SYMNMLEN];
struct {
unsigned long e_zeroes;
unsigned long e_offset;
} e;
} e;
unsigned long e_value;
unsigned short e_scnum;
unsigned short e_type;
char e_sclass[1];
char e_numaux[1];
};
#define N_BTMASK (0xf)
#define N_TMASK (0x30)
#define N_BTSHFT (4)
#define N_TSHIFT (2)
union external_auxent {
struct {
unsigned long x_tagndx; /* str, un, or enum tag indx */
union {
struct {
unsigned short x_lnno; /* declaration line number */
unsigned short x_size; /* str/union/array size */
} x_lnsz;
unsigned long x_fsize; /* size of function */
} x_misc;
union {
struct { /* if ISFCN, tag, or .bb */
unsigned long x_lnnoptr;/* ptr to fcn line # */
unsigned long x_endndx; /* entry ndx past block end */
} x_fcn;
struct { /* if ISARY, up to 4 dimen. */
char x_dimen[E_DIMNUM][2];
} x_ary;
} x_fcnary;
unsigned short x_tvndx; /* tv index */
} x_sym;
union {
char x_fname[E_FILNMLEN];
struct {
unsigned long x_zeroes;
unsigned long x_offset;
} x_n;
} x_file;
struct {
unsigned long x_scnlen; /* section length */
unsigned short x_nreloc; /* # relocation entries */
unsigned short x_nlinno; /* # line numbers */
unsigned long x_checksum; /* section COMDAT checksum */
unsigned short x_associated;/* COMDAT associated section index */
char x_comdat[1]; /* COMDAT selection number */
} x_scn;
struct {
unsigned long x_tvfill; /* tv fill value */
unsigned short x_tvlen; /* length of .tv */
char x_tvran[2][2]; /* tv range */
} x_tv; /* info about .tv section (in auxent of symbol .tv)) */
};
#define SYMENT struct external_syment
#define SYMESZ 18
#define AUXENT union external_auxent
#define AUXESZ 18
#define _ETEXT "etext"
/********************** RELOCATION DIRECTIVES **********************/
struct external_reloc {
char r_vaddr[4];
char r_symndx[4];
char r_type[2];
};
#define RELOC struct external_reloc
#define RELSZ 10
/* end of coff/i386.h */
/* PE COFF header information */
#ifndef _PE_H
#define _PE_H
/* NT specific file attributes */
#define IMAGE_FILE_RELOCS_STRIPPED 0x0001
#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002
#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004
#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008
#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080
#define IMAGE_FILE_32BIT_MACHINE 0x0100
#define IMAGE_FILE_DEBUG_STRIPPED 0x0200
#define IMAGE_FILE_SYSTEM 0x1000
#define IMAGE_FILE_DLL 0x2000
#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000
/* additional flags to be set for section headers to allow the NT loader to
read and write to the section data (to replace the addresses of data in
dlls for one thing); also to execute the section in .text's case=
*/
#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000
#define IMAGE_SCN_MEM_EXECUTE 0x20000000
#define IMAGE_SCN_MEM_READ 0x40000000
#define IMAGE_SCN_MEM_WRITE 0x80000000
/*
* Section characteristics added for ppc-nt
*/
#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* Reserved. */
#define IMAGE_SCN_CNT_CODE 0x00000020 /* Section contains code. */
#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* Section contains initialized data. */
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* Section contains uninitialized data. */
#define IMAGE_SCN_LNK_OTHER 0x00000100 /* Reserved. */
#define IMAGE_SCN_LNK_INFO 0x00000200 /* Section contains comments or some other type of information. */
#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* Section contents will not become part of image. */
#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* Section contents comdat. */
#define IMAGE_SCN_MEM_FARDATA 0x00008000
#define IMAGE_SCN_MEM_PURGEABLE 0x00020000
#define IMAGE_SCN_MEM_16BIT 0x00020000
#define IMAGE_SCN_MEM_LOCKED 0x00040000
#define IMAGE_SCN_MEM_PRELOAD 0x00080000
#define IMAGE_SCN_ALIGN_1BYTES 0x00100000
#define IMAGE_SCN_ALIGN_2BYTES 0x00200000
#define IMAGE_SCN_ALIGN_4BYTES 0x00300000
#define IMAGE_SCN_ALIGN_8BYTES 0x00400000
#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 /* Default alignment if no others are specified. */
#define IMAGE_SCN_ALIGN_32BYTES 0x00600000
#define IMAGE_SCN_ALIGN_64BYTES 0x00700000
#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* Section contains extended relocations. */
#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* Section is not cachable. */
#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* Section is not pageable. */
#define IMAGE_SCN_MEM_SHARED 0x10000000 /* Section is shareable. */
/* COMDAT selection codes. */
#define IMAGE_COMDAT_SELECT_NODUPLICATES (1) /* Warn if duplicates. */
#define IMAGE_COMDAT_SELECT_ANY (2) /* No warning. */
#define IMAGE_COMDAT_SELECT_SAME_SIZE (3) /* Warn if different size. */
#define IMAGE_COMDAT_SELECT_EXACT_MATCH (4) /* Warn if different. */
#define IMAGE_COMDAT_SELECT_ASSOCIATIVE (5) /* Base on other section. */
/* Magic values that are true for all dos/nt implementations */
#define DOSMAGIC 0x5a4d
#define NT_SIGNATURE 0x00004550
/* NT allows long filenames, we want to accommodate this. This may break
some of the bfd functions */
#undef FILNMLEN
#define FILNMLEN 18 /* # characters in a file name */
#ifdef COFF_IMAGE_WITH_PE
/* The filehdr is only weired in images */
#undef FILHDR
struct external_PE_filehdr
{
/* DOS header fields */
unsigned short e_magic; /* Magic number, 0x5a4d */
unsigned short e_cblp; /* Bytes on last page of file, 0x90 */
unsigned short e_cp; /* Pages in file, 0x3 */
unsigned short e_crlc; /* Relocations, 0x0 */
unsigned short e_cparhdr; /* Size of header in paragraphs, 0x4 */
unsigned short e_minalloc; /* Minimum extra paragraphs needed, 0x0 */
unsigned short e_maxalloc; /* Maximum extra paragraphs needed, 0xFFFF */
unsigned short e_ss; /* Initial (relative) SS value, 0x0 */
unsigned short e_sp; /* Initial SP value, 0xb8 */
unsigned short e_csum; /* Checksum, 0x0 */
unsigned short e_ip; /* Initial IP value, 0x0 */
unsigned short e_cs; /* Initial (relative) CS value, 0x0 */
unsigned short e_lfarlc; /* File address of relocation table, 0x40 */
unsigned short e_ovno; /* Overlay number, 0x0 */
char e_res[4][2]; /* Reserved words, all 0x0 */
unsigned short e_oemid; /* OEM identifier (for e_oeminfo), 0x0 */
unsigned short e_oeminfo; /* OEM information; e_oemid specific, 0x0 */
char e_res2[10][2]; /* Reserved words, all 0x0 */
unsigned long e_lfanew; /* File address of new exe header, 0x80 */
char dos_message[16][4]; /* other stuff, always follow DOS header */
unsigned int nt_signature; /* required NT signature, 0x4550 */
/* From standard header */
unsigned short f_magic; /* magic number */
unsigned short f_nscns; /* number of sections */
unsigned long f_timdat; /* time & date stamp */
unsigned long f_symptr; /* file pointer to symtab */
unsigned long f_nsyms; /* number of symtab entries */
unsigned short f_opthdr; /* sizeof(optional hdr) */
unsigned short f_flags; /* flags */
};
#define FILHDR struct external_PE_filehdr
#undef FILHSZ
#define FILHSZ 152
#endif
typedef struct
{
unsigned short magic; /* type of file */
unsigned short vstamp; /* version stamp */
unsigned long tsize; /* text size in bytes, padded to FW bdry*/
unsigned long dsize; /* initialized data " " */
unsigned long bsize; /* uninitialized data " " */
unsigned long entry; /* entry pt. */
unsigned long text_start; /* base of text used for this file */
unsigned long data_start; /* base of all data used for this file */
/* NT extra fields; see internal.h for descriptions */
unsigned long ImageBase;
unsigned long SectionAlignment;
unsigned long FileAlignment;
unsigned short MajorOperatingSystemVersion;
unsigned short MinorOperatingSystemVersion;
unsigned short MajorImageVersion;
unsigned short MinorImageVersion;
unsigned short MajorSubsystemVersion;
unsigned short MinorSubsystemVersion;
char Reserved1[4];
unsigned long SizeOfImage;
unsigned long SizeOfHeaders;
unsigned long CheckSum;
unsigned short Subsystem;
unsigned short DllCharacteristics;
unsigned long SizeOfStackReserve;
unsigned long SizeOfStackCommit;
unsigned long SizeOfHeapReserve;
unsigned long SizeOfHeapCommit;
unsigned long LoaderFlags;
unsigned long NumberOfRvaAndSizes;
/* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */
char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars */
} PEAOUTHDR;
#undef AOUTSZ
#define AOUTSZ (AOUTHDRSZ + 196)
#undef E_FILNMLEN
#define E_FILNMLEN 18 /* # characters in a file name */
#endif
/* end of coff/pe.h */
#define DT_NON (0) /* no derived type */
#define DT_PTR (1) /* pointer */
#define DT_FCN (2) /* function */
#define DT_ARY (3) /* array */
#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT))
#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT))
#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT))
#ifdef __cplusplus
}
#endif
#endif /* _A_OUT_H_ */

171
amd64.ld Normal file
View File

@@ -0,0 +1,171 @@
/* Default linker script, for normal executables */
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); SEARCH_DIR("/usr/local/lib64");
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0x60000000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
.rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
.rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
.rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init :
{
KEEP (*(.init))
} =0x90909090
.plt : { *(.plt) }
.text :
{
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} =0x90909090
.fini :
{
KEEP (*(.fini))
} =0x90909090
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.eh_frame_hdr : { *(.eh_frame_hdr) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN (0x100000) - ((0x100000 - .) & (0x100000 - 1)); . = DATA_SEGMENT_ALIGN (0x100000, 0x1000);
/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
the linker would then create the section even if it turns out to
be empty, which isn't pretty. */
. = ALIGN(64 / 8);
PROVIDE (__preinit_array_start = .);
.preinit_array : { *(.preinit_array) }
PROVIDE (__preinit_array_end = .);
PROVIDE (__init_array_start = .);
.init_array : { *(.init_array) }
PROVIDE (__init_array_end = .);
PROVIDE (__fini_array_start = .);
.fini_array : { *(.fini_array) }
PROVIDE (__fini_array_end = .);
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table) }
.dynamic : { *(.dynamic) }
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.got : { *(.got.plt) *(.got) }
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
. = ALIGN(64 / 8);
}
. = ALIGN(64 / 8);
_end = .;
PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}

273
block.c
View File

@@ -21,66 +21,92 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <getopt.h>
#include <inttypes.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <malloc.h>
#include <termios.h>
#include <sys/poll.h>
#include <errno.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include "vl.h"
#define NO_THUNK_TYPE_SIZE
#include "thunk.h"
#ifndef _WIN32
#include <sys/mman.h>
#endif
#include "cow.h"
struct BlockDriverState {
int fd; /* if -1, only COW mappings */
int64_t total_sectors;
int read_only;
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 */
/* event callback when inserting/removing */
void (*change_cb)(void *opaque);
void *change_opaque;
uint8_t *cow_bitmap; /* if non NULL, COW mappings are used first */
uint8_t *cow_bitmap_addr; /* mmap address of cow_bitmap */
int cow_bitmap_size;
int cow_fd;
int64_t cow_sectors_offset;
int boot_sector_enabled;
uint8_t boot_sector_data[512];
char filename[1024];
/* NOTE: the following infos are only hints for real hardware
drivers. They are not used by the block driver */
int cyls, heads, secs;
int type;
char device_name[32];
BlockDriverState *next;
};
BlockDriverState *bdrv_open(const char *filename, int snapshot)
{
BlockDriverState *bs;
int fd, cow_fd;
int64_t size;
char template[] = "/tmp/vl.XXXXXX";
struct cow_header_v2 cow_header;
struct stat st;
static BlockDriverState *bdrv_first;
bs = malloc(sizeof(BlockDriverState));
/* create a new block device (by default it is empty) */
BlockDriverState *bdrv_new(const char *device_name)
{
BlockDriverState **pbs, *bs;
bs = qemu_mallocz(sizeof(BlockDriverState));
if(!bs)
return NULL;
pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
/* insert at the end */
pbs = &bdrv_first;
while (*pbs != NULL)
pbs = &(*pbs)->next;
*pbs = bs;
return bs;
}
int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
{
int fd;
int64_t size;
struct cow_header_v2 cow_header;
#ifndef _WIN32
char template[] = "/tmp/vl.XXXXXX";
int cow_fd;
struct stat st;
#endif
bs->read_only = 0;
bs->fd = -1;
bs->cow_fd = -1;
bs->cow_bitmap = NULL;
strcpy(bs->filename, filename);
pstrcpy(bs->filename, sizeof(bs->filename), filename);
/* open standard HD image */
#ifdef _WIN32
fd = open(filename, O_RDWR | O_BINARY);
#else
fd = open(filename, O_RDWR | O_LARGEFILE);
#endif
if (fd < 0) {
/* read only image on disk */
#ifdef _WIN32
fd = open(filename, O_RDONLY | O_BINARY);
#else
fd = open(filename, O_RDONLY | O_LARGEFILE);
#endif
if (fd < 0) {
perror(filename);
goto fail;
@@ -95,8 +121,9 @@ BlockDriverState *bdrv_open(const char *filename, int snapshot)
fprintf(stderr, "%s: could not read header\n", filename);
goto fail;
}
if (cow_header.magic == htonl(COW_MAGIC) &&
cow_header.version == htonl(COW_VERSION)) {
#ifndef _WIN32
if (be32_to_cpu(cow_header.magic) == COW_MAGIC &&
be32_to_cpu(cow_header.version) == COW_VERSION) {
/* cow image found */
size = cow_header.size;
#ifndef WORDS_BIGENDIAN
@@ -111,7 +138,7 @@ BlockDriverState *bdrv_open(const char *filename, int snapshot)
fprintf(stderr, "%s: could not find original disk image '%s'\n", filename, cow_header.backing_file);
goto fail;
}
if (st.st_mtime != htonl(cow_header.mtime)) {
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;
}
@@ -131,16 +158,19 @@ BlockDriverState *bdrv_open(const char *filename, int snapshot)
bs->cow_bitmap = bs->cow_bitmap_addr + sizeof(cow_header);
bs->cow_sectors_offset = (bs->cow_bitmap_size + 511) & ~511;
snapshot = 0;
} else {
} else
#endif
{
/* standard raw image */
size = lseek64(fd, 0, SEEK_END);
bs->total_sectors = size / 512;
bs->fd = fd;
}
#ifndef _WIN32
if (snapshot) {
/* create a temporary COW file */
cow_fd = mkstemp(template);
cow_fd = mkstemp64(template);
if (cow_fd < 0)
goto fail;
bs->cow_fd = cow_fd;
@@ -157,23 +187,44 @@ BlockDriverState *bdrv_open(const char *filename, int snapshot)
bs->cow_bitmap = bs->cow_bitmap_addr;
bs->cow_sectors_offset = 0;
}
#endif
return bs;
bs->inserted = 1;
/* call the change callback */
if (bs->change_cb)
bs->change_cb(bs->change_opaque);
return 0;
fail:
bdrv_close(bs);
return NULL;
return -1;
}
void bdrv_close(BlockDriverState *bs)
{
/* we unmap the mapping so that it is written to the COW file */
if (bs->cow_bitmap_addr)
munmap(bs->cow_bitmap_addr, bs->cow_bitmap_size);
if (bs->cow_fd >= 0)
close(bs->cow_fd);
if (bs->fd >= 0)
close(bs->fd);
free(bs);
if (bs->inserted) {
#ifndef _WIN32
/* we unmap the mapping so that it is written to the COW file */
if (bs->cow_bitmap_addr)
munmap(bs->cow_bitmap_addr, bs->cow_bitmap_size);
#endif
if (bs->cow_fd >= 0)
close(bs->cow_fd);
if (bs->fd >= 0)
close(bs->fd);
bs->inserted = 0;
/* call the change callback */
if (bs->change_cb)
bs->change_cb(bs->change_opaque);
}
}
void bdrv_delete(BlockDriverState *bs)
{
bdrv_close(bs);
qemu_free(bs);
}
static inline void set_bit(uint8_t *bitmap, int64_t bitnum)
@@ -216,6 +267,9 @@ int bdrv_commit(BlockDriverState *bs)
int64_t i;
uint8_t *cow_bitmap;
if (!bs->inserted)
return -1;
if (!bs->cow_bitmap) {
fprintf(stderr, "Already committed to %s\n", bs->filename);
return 0;
@@ -258,10 +312,17 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num,
int ret, n, fd;
int64_t offset;
if (!bs->inserted)
return -1;
while (nb_sectors > 0) {
if (is_changed(bs->cow_bitmap, sector_num, nb_sectors, &n)) {
fd = bs->cow_fd;
offset = bs->cow_sectors_offset;
} else if (sector_num == 0 && bs->boot_sector_enabled) {
memcpy(buf, bs->boot_sector_data, 512);
n = 1;
goto next;
} else {
fd = bs->fd;
offset = 0;
@@ -278,6 +339,7 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num,
return -1;
}
}
next:
nb_sectors -= n;
sector_num += n;
buf += n * 512;
@@ -291,7 +353,9 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
{
int ret, fd, i;
int64_t offset, retl;
if (!bs->inserted)
return -1;
if (bs->read_only)
return -1;
@@ -324,3 +388,116 @@ void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
{
*nb_sectors_ptr = bs->total_sectors;
}
/* force a given boot sector. */
void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
{
bs->boot_sector_enabled = 1;
if (size > 512)
size = 512;
memcpy(bs->boot_sector_data, data, size);
memset(bs->boot_sector_data + size, 0, 512 - size);
}
void bdrv_set_geometry_hint(BlockDriverState *bs,
int cyls, int heads, int secs)
{
bs->cyls = cyls;
bs->heads = heads;
bs->secs = secs;
}
void bdrv_set_type_hint(BlockDriverState *bs, int type)
{
bs->type = type;
bs->removable = ((type == BDRV_TYPE_CDROM ||
type == BDRV_TYPE_FLOPPY));
}
void bdrv_get_geometry_hint(BlockDriverState *bs,
int *pcyls, int *pheads, int *psecs)
{
*pcyls = bs->cyls;
*pheads = bs->heads;
*psecs = bs->secs;
}
int bdrv_get_type_hint(BlockDriverState *bs)
{
return bs->type;
}
int bdrv_is_removable(BlockDriverState *bs)
{
return bs->removable;
}
int bdrv_is_read_only(BlockDriverState *bs)
{
return bs->read_only;
}
int bdrv_is_inserted(BlockDriverState *bs)
{
return bs->inserted;
}
int bdrv_is_locked(BlockDriverState *bs)
{
return bs->locked;
}
void bdrv_set_locked(BlockDriverState *bs, int locked)
{
bs->locked = locked;
}
void bdrv_set_change_cb(BlockDriverState *bs,
void (*change_cb)(void *opaque), void *opaque)
{
bs->change_cb = change_cb;
bs->change_opaque = opaque;
}
BlockDriverState *bdrv_find(const char *name)
{
BlockDriverState *bs;
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
if (!strcmp(name, bs->device_name))
return bs;
}
return NULL;
}
void bdrv_info(void)
{
BlockDriverState *bs;
for (bs = bdrv_first; bs != NULL; bs = bs->next) {
term_printf("%s:", bs->device_name);
term_printf(" type=");
switch(bs->type) {
case BDRV_TYPE_HD:
term_printf("hd");
break;
case BDRV_TYPE_CDROM:
term_printf("cdrom");
break;
case BDRV_TYPE_FLOPPY:
term_printf("floppy");
break;
}
term_printf(" removable=%d", bs->removable);
if (bs->removable) {
term_printf(" locked=%d", bs->locked);
}
if (bs->inserted) {
term_printf(" file=%s", bs->filename);
term_printf(" ro=%d", bs->read_only);
} else {
term_printf(" [not inserted]");
}
term_printf("\n");
}
}

76
bswap.h Normal file
View File

@@ -0,0 +1,76 @@
#ifndef BSWAP_H
#define BSWAP_H
#include "config-host.h"
#include <inttypes.h>
#ifdef HAVE_BYTESWAP_H
#include <byteswap.h>
#else
#define bswap_16(x) \
({ \
uint16_t __x = (x); \
((uint16_t)( \
(((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
(((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
})
#define bswap_32(x) \
({ \
uint32_t __x = (x); \
((uint32_t)( \
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
})
#define bswap_64(x) \
({ \
uint64_t __x = (x); \
((uint64_t)( \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
})
#endif /* !HAVE_BYTESWAP_H */
static inline uint16_t bswap16(uint16_t x)
{
return bswap_16(x);
}
static inline uint32_t bswap32(uint32_t x)
{
return bswap_32(x);
}
static inline uint64_t bswap64(uint64_t x)
{
return bswap_64(x);
}
static inline void bswap16s(uint16_t *s)
{
*s = bswap16(*s);
}
static inline void bswap32s(uint32_t *s)
{
*s = bswap32(*s);
}
static inline void bswap64s(uint64_t *s)
{
*s = bswap64(*s);
}
#endif /* BSWAP_H */

418
configure vendored
View File

@@ -15,11 +15,10 @@ TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c"
TMPO="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.o"
TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}"
TMPS="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.S"
TMPH="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.h"
# default parameters
prefix="/usr/local"
interp_prefix="/usr/gnemul/qemu-i386"
prefix=""
interp_prefix="/usr/gnemul/qemu-%M"
static="no"
cross_prefix=""
cc="gcc"
@@ -27,12 +26,11 @@ host_cc="gcc"
ar="ar"
make="make"
strip="strip"
target_cpu="x86"
target_bigendian="default"
cpu=`uname -m`
target_list="i386-user i386 i386-softmmu arm-user sparc-user ppc-user ppc-softmmu"
case "$cpu" in
i386|i486|i586|i686|i86pc|BePC)
cpu="x86"
cpu="i386"
;;
armv4l)
cpu="armv4l"
@@ -58,19 +56,52 @@ case "$cpu" in
ia64)
cpu="ia64"
;;
m68k)
cpu="m68k"
;;
x86_64|amd64)
cpu="amd64"
;;
*)
cpu="unknown"
;;
esac
gprof="no"
bigendian="no"
mingw32="no"
EXESUF=""
gdbstub="yes"
slirp="yes"
# OS specific
targetos=`uname -s`
case $targetos in
MINGW32*)
mingw32="yes"
;;
FreeBSD)
bsd="yes"
;;
NetBSD)
bsd="yes"
;;
OpenBSD)
bsd="yes"
;;
Darwin)
bsd="yes"
darwin="yes"
;;
*) ;;
esac
if [ "$bsd" = "yes" ] ; then
if [ ! "$darwin" = "yes" ] ; then
make="gmake"
fi
target_list="i386-softmmu ppc-softmmu"
fi
# find source path
# XXX: we assume an absolute path is given when launching configure,
# except in './configure' case.
@@ -104,16 +135,18 @@ for opt do
;;
--cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
;;
--target-cpu=*) target_cpu=`echo $opt | cut -d '=' -f 2`
;;
--target-big-endian) target_bigendian="yes"
;;
--target-little-endian) target_bigendian="no"
--target-list=*) target_list=${opt#--target-list=}
;;
--enable-gprof) gprof="yes"
;;
--static) static="yes"
;;
--disable-sdl) sdl="no"
;;
--enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-"
;;
--disable-slirp) slirp="no"
;;
esac
done
@@ -126,6 +159,13 @@ cc="${cross_prefix}${cc}"
ar="${cross_prefix}${ar}"
strip="${cross_prefix}${strip}"
if test "$mingw32" = "yes" ; then
target_list="i386-softmmu ppc-softmmu"
EXESUF=".exe"
gdbstub="no"
slirp="no"
fi
if test -z "$cross_prefix" ; then
# ---
@@ -147,7 +187,7 @@ fi
else
# if cross compiling, cannot launch a program, so make a static guess
if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64"; then
if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k"; then
bigendian="yes"
fi
@@ -164,16 +204,57 @@ if $cc -fno-reorder-blocks -fno-optimize-sibling-calls -o $TMPO $TMPC 2> /dev/nu
have_gcc3_options="yes"
fi
if test "$target_bigendian" = "default" ; then
if test "$target_cpu" = "x86" ; then
target_bigendian="no"
elif test "$target_cpu" = "arm" ; then
target_bigendian="no"
else
target_bigendian="no"
fi
##########################################
# SDL probe
sdl_too_old=no
if test -z "$sdl" ; then
sdl_config="sdl-config"
sdl=no
sdl_static=no
if test "$mingw32" = "yes" -a ! -z "$cross_prefix" ; then
# win32 cross compilation case
sdl_config="i386-mingw32msvc-sdl-config"
sdl=yes
else
# normal SDL probe
cat > $TMPC << EOF
#include <SDL.h>
#undef main /* We don't want SDL to override our main() */
int main( void ) { return SDL_Init (SDL_INIT_VIDEO); }
EOF
if $cc -o $TMPE `$sdl_config --cflags 2> /dev/null` $TMPC `$sdl_config --libs 2> /dev/null` 2> /dev/null ; then
_sdlversion=`$sdl_config --version | sed 's/[^0-9]//g'`
if test "$_sdlversion" -lt 121 ; then
sdl_too_old=yes
else
sdl=yes
fi
# static link with sdl ?
if test "$sdl" = "yes" ; then
aa="no"
`$sdl_config --static-libs | grep \\\-laa > /dev/null` && aa="yes"
sdl_static_libs=`$sdl_config --static-libs`
if [ "$aa" = "yes" ] ; then
sdl_static_libs="$sdl_static_libs `aalib-config --static-libs`"
fi
if $cc -o $TMPE `$sdl_config --cflags 2> /dev/null` $TMPC $sdl_static_libs 2> /dev/null; then
sdl_static=yes
fi
fi # static link
fi # sdl compile test
fi # cross compilation
fi # -z $sdl
if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
cat << EOF
@@ -184,8 +265,9 @@ EOF
echo "Standard options:"
echo " --help print this message"
echo " --prefix=PREFIX install in PREFIX [$prefix]"
echo " --interp-prefix=PREFIX where to find shared libraries, etc. [$interp_prefix]"
echo " --target_cpu=CPU set target cpu (x86 or arm) [$target_cpu]"
echo " --interp-prefix=PREFIX where to find shared libraries, etc."
echo " use %M for cpu name [$interp_prefix]"
echo " --target-list=LIST set target list [$target_list]"
echo ""
echo "Advanced options (experts only):"
echo " --source-path=PATH path of source code [$source_path]"
@@ -193,106 +275,266 @@ echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
echo " --cc=CC use C compiler CC [$cc]"
echo " --make=MAKE use specified make [$make]"
echo " --static enable static build [$static]"
echo " --enable-mingw32 enable Win32 cross compilation with mingw32"
echo ""
echo "NOTE: The object files are build at the place where configure is launched"
exit 1
fi
if test "$mingw32" = "yes" ; then
if test -z "$prefix" ; then
prefix="/c/Program Files/Qemu"
fi
mandir="$prefix"
datadir="$prefix"
docdir="$prefix"
bindir="$prefix"
else
if test -z "$prefix" ; then
prefix="/usr/local"
fi
mandir="$prefix/share/man"
datadir="$prefix/share/qemu"
docdir="$prefix/share/doc/qemu"
bindir="$prefix/bin"
fi
echo "Install prefix $prefix"
echo "Source path $source_path"
echo "BIOS directory $datadir"
echo "binary directory $bindir"
if test "$mingw32" = "no" ; then
echo "Manual directory $mandir"
echo "ELF interp prefix $interp_prefix"
fi
echo "Source path $source_path"
echo "C compiler $cc"
echo "make $make"
echo "host CPU $cpu"
echo "host big endian $bigendian"
echo "target CPU $target_cpu"
echo "target big endian $target_bigendian"
echo "target list $target_list"
echo "gprof enabled $gprof"
echo "static build $static"
echo "SDL support $sdl"
echo "SDL static link $sdl_static"
echo "mingw32 support $mingw32"
echo "Creating config.mak and config.h"
echo "# Automatically generated by configure - do not modify" > config.mak
echo "/* Automatically generated by configure - do not modify */" > $TMPH
echo "prefix=$prefix" >> config.mak
echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix\"" >> $TMPH
echo "MAKE=$make" >> config.mak
echo "CC=$cc" >> config.mak
if test "$have_gcc3_options" = "yes" ; then
echo "HAVE_GCC3_OPTIONS=yes" >> config.mak
if test $sdl_too_old = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have FFplay/SDL support"
fi
echo "HOST_CC=$host_cc" >> config.mak
echo "AR=$ar" >> config.mak
echo "STRIP=$strip -s -R .comment -R .note" >> config.mak
echo "CFLAGS=$CFLAGS" >> config.mak
echo "LDFLAGS=$LDFLAGS" >> config.mak
if test "$cpu" = "x86" ; then
echo "ARCH=i386" >> config.mak
echo "#define HOST_I386 1" >> $TMPH
if test "$sdl_static" = "no"; then
echo "WARNING: cannot compile statically with SDL - qemu-fast won't have a graphical output"
fi
config_mak="config-host.mak"
config_h="config-host.h"
#echo "Creating $config_mak and $config_h"
echo "# Automatically generated by configure - do not modify" > $config_mak
echo "/* Automatically generated by configure - do not modify */" > $config_h
echo "prefix=$prefix" >> $config_mak
echo "bindir=$bindir" >> $config_mak
echo "mandir=$mandir" >> $config_mak
echo "datadir=$datadir" >> $config_mak
echo "docdir=$docdir" >> $config_mak
echo "#define CONFIG_QEMU_SHAREDIR \"$datadir\"" >> $config_h
echo "MAKE=$make" >> $config_mak
echo "CC=$cc" >> $config_mak
if test "$have_gcc3_options" = "yes" ; then
echo "HAVE_GCC3_OPTIONS=yes" >> $config_mak
fi
echo "HOST_CC=$host_cc" >> $config_mak
echo "AR=$ar" >> $config_mak
echo "STRIP=$strip -s -R .comment -R .note" >> $config_mak
echo "CFLAGS=$CFLAGS" >> $config_mak
echo "LDFLAGS=$LDFLAGS" >> $config_mak
echo "EXESUF=$EXESUF" >> $config_mak
if test "$cpu" = "i386" ; then
echo "ARCH=i386" >> $config_mak
echo "#define HOST_I386 1" >> $config_h
elif test "$cpu" = "amd64" ; then
echo "ARCH=amd64" >> $config_mak
echo "#define HOST_AMD64 1" >> $config_h
elif test "$cpu" = "armv4l" ; then
echo "ARCH=arm" >> config.mak
echo "#define HOST_ARM 1" >> $TMPH
echo "ARCH=arm" >> $config_mak
echo "#define HOST_ARM 1" >> $config_h
elif test "$cpu" = "powerpc" ; then
echo "ARCH=ppc" >> config.mak
echo "#define HOST_PPC 1" >> $TMPH
echo "ARCH=ppc" >> $config_mak
echo "#define HOST_PPC 1" >> $config_h
elif test "$cpu" = "mips" ; then
echo "ARCH=mips" >> config.mak
echo "#define HOST_MIPS 1" >> $TMPH
echo "ARCH=mips" >> $config_mak
echo "#define HOST_MIPS 1" >> $config_h
elif test "$cpu" = "s390" ; then
echo "ARCH=s390" >> config.mak
echo "#define HOST_S390 1" >> $TMPH
echo "ARCH=s390" >> $config_mak
echo "#define HOST_S390 1" >> $config_h
elif test "$cpu" = "alpha" ; then
echo "ARCH=alpha" >> config.mak
echo "#define HOST_ALPHA 1" >> $TMPH
echo "ARCH=alpha" >> $config_mak
echo "#define HOST_ALPHA 1" >> $config_h
elif test "$cpu" = "sparc" ; then
echo "ARCH=sparc" >> config.mak
echo "#define HOST_SPARC 1" >> $TMPH
echo "ARCH=sparc" >> $config_mak
echo "#define HOST_SPARC 1" >> $config_h
elif test "$cpu" = "sparc64" ; then
echo "ARCH=sparc64" >> config.mak
echo "#define HOST_SPARC64 1" >> $TMPH
echo "ARCH=sparc64" >> $config_mak
echo "#define HOST_SPARC64 1" >> $config_h
elif test "$cpu" = "ia64" ; then
echo "ARCH=ia64" >> config.mak
echo "#define HOST_IA64 1" >> $TMPH
echo "ARCH=ia64" >> $config_mak
echo "#define HOST_IA64 1" >> $config_h
elif test "$cpu" = "m68k" ; then
echo "ARCH=m68k" >> $config_mak
echo "#define HOST_M68K 1" >> $config_h
else
echo "Unsupported CPU"
exit 1
fi
if test "$bigendian" = "yes" ; then
echo "WORDS_BIGENDIAN=yes" >> config.mak
echo "#define WORDS_BIGENDIAN 1" >> $TMPH
echo "WORDS_BIGENDIAN=yes" >> $config_mak
echo "#define WORDS_BIGENDIAN 1" >> $config_h
fi
if test "$mingw32" = "yes" ; then
echo "CONFIG_WIN32=yes" >> $config_mak
echo "#define CONFIG_WIN32 1" >> $config_h
elif test -f "/usr/include/byteswap.h" ; then
echo "#define HAVE_BYTESWAP_H 1" >> $config_h
fi
if test "$darwin" = "yes" ; then
echo "CONFIG_DARWIN=yes" >> $config_mak
echo "#define CONFIG_DARWIN 1" >> $config_h
fi
if test "$gdbstub" = "yes" ; then
echo "CONFIG_GDBSTUB=yes" >> $config_mak
echo "#define CONFIG_GDBSTUB 1" >> $config_h
fi
if test "$gprof" = "yes" ; then
echo "TARGET_GPROF=yes" >> $config_mak
echo "#define HAVE_GPROF 1" >> $config_h
fi
if test "$static" = "yes" ; then
echo "CONFIG_STATIC=yes" >> $config_mak
echo "#define CONFIG_STATIC 1" >> $config_h
fi
if test "$slirp" = "yes" ; then
echo "CONFIG_SLIRP=yes" >> $config_mak
echo "#define CONFIG_SLIRP 1" >> $config_h
fi
echo -n "VERSION=" >>$config_mak
head $source_path/VERSION >>$config_mak
echo "" >>$config_mak
echo -n "#define QEMU_VERSION \"" >> $config_h
head $source_path/VERSION >> $config_h
echo "\"" >> $config_h
echo "SRC_PATH=$source_path" >> $config_mak
echo "TARGET_DIRS=$target_list" >> $config_mak
# XXX: suppress that
if [ "$bsd" = "yes" ] ; then
echo "#define O_LARGEFILE 0" >> $config_h
echo "#define lseek64 lseek" >> $config_h
echo "#define mkstemp64 mkstemp" >> $config_h
echo "#define ftruncate64 ftruncate" >> $config_h
echo "#define off64_t off_t" >> $config_h
echo "#define MAP_ANONYMOUS MAP_ANON" >> $config_h
echo "#define _BSD 1" >> $config_h
fi
if test "$target_cpu" = "x86" ; then
echo "TARGET_ARCH=i386" >> config.mak
echo "#define TARGET_ARCH \"i386\"" >> $TMPH
echo "#define TARGET_I386 1" >> $TMPH
for target in $target_list; do
target_dir="$target"
config_mak=$target_dir/config.mak
config_h=$target_dir/config.h
target_cpu=`echo $target | cut -d '-' -f 1`
target_bigendian="no"
[ "$target_cpu" = "sparc" ] && target_bigendian=yes
[ "$target_cpu" = "ppc" ] && target_bigendian=yes
target_softmmu="no"
if expr $target : '.*-softmmu' > /dev/null ; then
target_softmmu="yes"
fi
target_user_only="no"
if expr $target : '.*-user' > /dev/null ; then
target_user_only="yes"
fi
#echo "Creating $config_mak, $config_h and $target_dir/Makefile"
mkdir -p $target_dir
if test "$target" = "arm-user" ; then
mkdir -p $target_dir/nwfpe
fi
if test "$target_user_only" = "no" ; then
mkdir -p $target_dir/slirp
fi
ln -sf $source_path/Makefile.target $target_dir/Makefile
echo "# Automatically generated by configure - do not modify" > $config_mak
echo "/* Automatically generated by configure - do not modify */" > $config_h
echo "include ../config-host.mak" >> $config_mak
echo "#include \"../config-host.h\"" >> $config_h
interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
if test "$target_cpu" = "i386" ; then
echo "TARGET_ARCH=i386" >> $config_mak
echo "#define TARGET_ARCH \"i386\"" >> $config_h
echo "#define TARGET_I386 1" >> $config_h
elif test "$target_cpu" = "arm" ; then
echo "TARGET_ARCH=arm" >> config.mak
echo "#define TARGET_ARCH \"arm\"" >> $TMPH
echo "#define TARGET_ARM 1" >> $TMPH
echo "TARGET_ARCH=arm" >> $config_mak
echo "#define TARGET_ARCH \"arm\"" >> $config_h
echo "#define TARGET_ARM 1" >> $config_h
elif test "$target_cpu" = "sparc" ; then
echo "TARGET_ARCH=sparc" >> $config_mak
echo "#define TARGET_ARCH \"sparc\"" >> $config_h
echo "#define TARGET_SPARC 1" >> $config_h
elif test "$target_cpu" = "ppc" ; then
echo "TARGET_ARCH=ppc" >> $config_mak
echo "#define TARGET_ARCH \"ppc\"" >> $config_h
echo "#define TARGET_PPC 1" >> $config_h
else
echo "Unsupported target CPU"
exit 1
fi
if test "$target_bigendian" = "yes" ; then
echo "TARGET_WORDS_BIGENDIAN=yes" >> config.mak
echo "#define TARGET_WORDS_BIGENDIAN 1" >> $TMPH
echo "TARGET_WORDS_BIGENDIAN=yes" >> $config_mak
echo "#define TARGET_WORDS_BIGENDIAN 1" >> $config_h
fi
if test "$target_softmmu" = "yes" ; then
echo "CONFIG_SOFTMMU=yes" >> $config_mak
echo "#define CONFIG_SOFTMMU 1" >> $config_h
fi
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 "$gprof" = "yes" ; then
echo "TARGET_GPROF=yes" >> config.mak
echo "#define HAVE_GPROF 1" >> $TMPH
# sdl defines
if test "$target_user_only" = "no"; then
if test "$target_softmmu" = "no" -o "$static" = "yes"; then
if test "$sdl_static" = "yes" ; then
echo "#define CONFIG_SDL 1" >> $config_h
echo "CONFIG_SDL=yes" >> $config_mak
echo "SDL_LIBS=$sdl_static_libs" >> $config_mak
fi
else
if test "$sdl" = "yes" ; then
echo "#define CONFIG_SDL 1" >> $config_h
echo "CONFIG_SDL=yes" >> $config_mak
echo "SDL_LIBS=`$sdl_config --libs`" >> $config_mak
fi
fi
echo -n "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak
if [ "${aa}" = "yes" ] ; then
echo -n " `aalib-config --cflags`" >> $config_mak ;
fi
echo "" >> $config_mak
fi
if test "$static" = "yes" ; then
echo "CONFIG_STATIC=yes" >> config.mak
fi
echo -n "VERSION=" >>config.mak
head $source_path/VERSION >>config.mak
echo "" >>config.mak
echo -n "#define QEMU_VERSION \"" >> $TMPH
head $source_path/VERSION >> $TMPH
echo "\"" >> $TMPH
done # for target in $targets
# build tree in object directory if source path is different from current one
if test "$source_path_used" = "yes" ; then
@@ -305,13 +547,5 @@ if test "$source_path_used" = "yes" ; then
ln -sf $source_path/$f $f
done
fi
echo "SRC_PATH=$source_path" >> config.mak
diff $TMPH config.h >/dev/null 2>&1
if test $? -ne 0 ; then
mv -f $TMPH config.h
else
echo "config.h is unchanged"
fi
rm -f $TMPO $TMPC $TMPE $TMPS $TMPH
rm -f $TMPO $TMPC $TMPE $TMPS

13
cow.h Normal file
View File

@@ -0,0 +1,13 @@
/* user mode linux compatible COW file */
#define COW_MAGIC 0x4f4f4f4d /* MOOO */
#define COW_VERSION 2
struct cow_header_v2 {
uint32_t magic;
uint32_t version;
char backing_file[1024];
int32_t mtime;
uint64_t size;
uint32_t sectorsize;
};

568
cpu-all.h
View File

@@ -20,18 +20,163 @@
#ifndef CPU_ALL_H
#define CPU_ALL_H
/* all CPU memory access use these macros */
static inline int ldub(void *ptr)
#if defined(__arm__) || defined(__sparc__)
#define WORDS_ALIGNED
#endif
/* some important defines:
*
* WORDS_ALIGNED : if defined, the host cpu can only make word aligned
* memory accesses.
*
* WORDS_BIGENDIAN : if defined, the host cpu is big endian and
* otherwise little endian.
*
* (TARGET_WORDS_ALIGNED : same for target cpu (not supported yet))
*
* TARGET_WORDS_BIGENDIAN : same for target cpu
*/
#include "bswap.h"
#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
#define BSWAP_NEEDED
#endif
#ifdef BSWAP_NEEDED
static inline uint16_t tswap16(uint16_t s)
{
return bswap16(s);
}
static inline uint32_t tswap32(uint32_t s)
{
return bswap32(s);
}
static inline uint64_t tswap64(uint64_t s)
{
return bswap64(s);
}
static inline void tswap16s(uint16_t *s)
{
*s = bswap16(*s);
}
static inline void tswap32s(uint32_t *s)
{
*s = bswap32(*s);
}
static inline void tswap64s(uint64_t *s)
{
*s = bswap64(*s);
}
#else
static inline uint16_t tswap16(uint16_t s)
{
return s;
}
static inline uint32_t tswap32(uint32_t s)
{
return s;
}
static inline uint64_t tswap64(uint64_t s)
{
return s;
}
static inline void tswap16s(uint16_t *s)
{
}
static inline void tswap32s(uint32_t *s)
{
}
static inline void tswap64s(uint64_t *s)
{
}
#endif
#if TARGET_LONG_SIZE == 4
#define tswapl(s) tswap32(s)
#define tswapls(s) tswap32s((uint32_t *)(s))
#else
#define tswapl(s) tswap64(s)
#define tswapls(s) tswap64s((uint64_t *)(s))
#endif
/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
typedef union {
double d;
#if !defined(WORDS_BIGENDIAN) && !defined(__arm__)
struct {
uint32_t lower;
uint32_t upper;
} l;
#else
struct {
uint32_t upper;
uint32_t lower;
} l;
#endif
uint64_t ll;
} CPU_DoubleU;
/* CPU memory access without any memory or io remapping */
/*
* the generic syntax for the memory accesses is:
*
* load: ld{type}{sign}{size}{endian}_{access_type}(ptr)
*
* store: st{type}{size}{endian}_{access_type}(ptr, val)
*
* type is:
* (empty): integer access
* f : float access
*
* sign is:
* (empty): for floats or 32 bit size
* u : unsigned
* s : signed
*
* size is:
* b: 8 bits
* w: 16 bits
* l: 32 bits
* q: 64 bits
*
* endian is:
* (empty): target cpu endianness or 8 bit access
* r : reversed target cpu endianness (not implemented yet)
* be : big endian (not implemented yet)
* le : little endian (not implemented yet)
*
* access_type is:
* raw : host memory access
* user : user mode access using soft MMU
* kernel : kernel mode access using soft MMU
*/
static inline int ldub_raw(void *ptr)
{
return *(uint8_t *)ptr;
}
static inline int ldsb(void *ptr)
static inline int ldsb_raw(void *ptr)
{
return *(int8_t *)ptr;
}
static inline void stb(void *ptr, int v)
static inline void stb_raw(void *ptr, int v)
{
*(uint8_t *)ptr = v;
}
@@ -39,10 +184,10 @@ static inline void stb(void *ptr, int v)
/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
kernel handles unaligned load/stores may give better results, but
it is a system wide setting : bad */
#if defined(WORDS_BIGENDIAN) || defined(__arm__)
#if !defined(TARGET_WORDS_BIGENDIAN) && (defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED))
/* conservative code for little endian unaligned accesses */
static inline int lduw(void *ptr)
static inline int lduw_raw(void *ptr)
{
#ifdef __powerpc__
int val;
@@ -54,7 +199,7 @@ static inline int lduw(void *ptr)
#endif
}
static inline int ldsw(void *ptr)
static inline int ldsw_raw(void *ptr)
{
#ifdef __powerpc__
int val;
@@ -66,7 +211,7 @@ static inline int ldsw(void *ptr)
#endif
}
static inline int ldl(void *ptr)
static inline int ldl_raw(void *ptr)
{
#ifdef __powerpc__
int val;
@@ -78,16 +223,16 @@ static inline int ldl(void *ptr)
#endif
}
static inline uint64_t ldq(void *ptr)
static inline uint64_t ldq_raw(void *ptr)
{
uint8_t *p = ptr;
uint32_t v1, v2;
v1 = ldl(p);
v2 = ldl(p + 4);
v1 = ldl_raw(p);
v2 = ldl_raw(p + 4);
return v1 | ((uint64_t)v2 << 32);
}
static inline void stw(void *ptr, int v)
static inline void stw_raw(void *ptr, int v)
{
#ifdef __powerpc__
__asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
@@ -98,7 +243,7 @@ static inline void stw(void *ptr, int v)
#endif
}
static inline void stl(void *ptr, int v)
static inline void stl_raw(void *ptr, int v)
{
#ifdef __powerpc__
__asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
@@ -111,154 +256,294 @@ static inline void stl(void *ptr, int v)
#endif
}
static inline void stq(void *ptr, uint64_t v)
static inline void stq_raw(void *ptr, uint64_t v)
{
uint8_t *p = ptr;
stl(p, (uint32_t)v);
stl(p + 4, v >> 32);
stl_raw(p, (uint32_t)v);
stl_raw(p + 4, v >> 32);
}
/* float access */
static inline float ldfl(void *ptr)
static inline float ldfl_raw(void *ptr)
{
union {
float f;
uint32_t i;
} u;
u.i = ldl(ptr);
u.i = ldl_raw(ptr);
return u.f;
}
static inline void stfl(void *ptr, float v)
static inline void stfl_raw(void *ptr, float v)
{
union {
float f;
uint32_t i;
} u;
u.f = v;
stl(ptr, u.i);
stl_raw(ptr, u.i);
}
#if defined(__arm__) && !defined(WORDS_BIGENDIAN)
/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
static inline double ldfq(void *ptr)
static inline double ldfq_raw(void *ptr)
{
union {
double d;
uint32_t tab[2];
} u;
u.tab[1] = ldl(ptr);
u.tab[0] = ldl(ptr + 4);
CPU_DoubleU u;
u.l.lower = ldl_raw(ptr);
u.l.upper = ldl_raw(ptr + 4);
return u.d;
}
static inline void stfq(void *ptr, double v)
static inline void stfq_raw(void *ptr, double v)
{
union {
double d;
uint32_t tab[2];
} u;
CPU_DoubleU u;
u.d = v;
stl(ptr, u.tab[1]);
stl(ptr + 4, u.tab[0]);
stl_raw(ptr, u.l.lower);
stl_raw(ptr + 4, u.l.upper);
}
#elif defined(TARGET_WORDS_BIGENDIAN) && (!defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED))
static inline int lduw_raw(void *ptr)
{
#if defined(__i386__)
int val;
asm volatile ("movzwl %1, %0\n"
"xchgb %b0, %h0\n"
: "=q" (val)
: "m" (*(uint16_t *)ptr));
return val;
#else
static inline double ldfq(void *ptr)
{
union {
double d;
uint64_t i;
} u;
u.i = ldq(ptr);
return u.d;
}
static inline void stfq(void *ptr, double v)
{
union {
double d;
uint64_t i;
} u;
u.d = v;
stq(ptr, u.i);
}
uint8_t *b = (uint8_t *) ptr;
return ((b[0] << 8) | b[1]);
#endif
}
static inline int ldsw_raw(void *ptr)
{
#if defined(__i386__)
int val;
asm volatile ("movzwl %1, %0\n"
"xchgb %b0, %h0\n"
: "=q" (val)
: "m" (*(uint16_t *)ptr));
return (int16_t)val;
#else
uint8_t *b = (uint8_t *) ptr;
return (int16_t)((b[0] << 8) | b[1]);
#endif
}
static inline int ldl_raw(void *ptr)
{
#if defined(__i386__) || defined(__x86_64__)
int val;
asm volatile ("movl %1, %0\n"
"bswap %0\n"
: "=r" (val)
: "m" (*(uint32_t *)ptr));
return val;
#else
uint8_t *b = (uint8_t *) ptr;
return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
#endif
}
static inline uint64_t ldq_raw(void *ptr)
{
uint32_t a,b;
a = ldl_raw(ptr);
b = ldl_raw(ptr+4);
return (((uint64_t)a<<32)|b);
}
static inline void stw_raw(void *ptr, int v)
{
#if defined(__i386__)
asm volatile ("xchgb %b0, %h0\n"
"movw %w0, %1\n"
: "=q" (v)
: "m" (*(uint16_t *)ptr), "0" (v));
#else
uint8_t *d = (uint8_t *) ptr;
d[0] = v >> 8;
d[1] = v;
#endif
}
static inline void stl_raw(void *ptr, int v)
{
#if defined(__i386__) || defined(__x86_64__)
asm volatile ("bswap %0\n"
"movl %0, %1\n"
: "=r" (v)
: "m" (*(uint32_t *)ptr), "0" (v));
#else
uint8_t *d = (uint8_t *) ptr;
d[0] = v >> 24;
d[1] = v >> 16;
d[2] = v >> 8;
d[3] = v;
#endif
}
static inline void stq_raw(void *ptr, uint64_t v)
{
stl_raw(ptr, v >> 32);
stl_raw(ptr + 4, v);
}
/* float access */
static inline float ldfl_raw(void *ptr)
{
union {
float f;
uint32_t i;
} u;
u.i = ldl_raw(ptr);
return u.f;
}
static inline void stfl_raw(void *ptr, float v)
{
union {
float f;
uint32_t i;
} u;
u.f = v;
stl_raw(ptr, u.i);
}
static inline double ldfq_raw(void *ptr)
{
CPU_DoubleU u;
u.l.upper = ldl_raw(ptr);
u.l.lower = ldl_raw(ptr + 4);
return u.d;
}
static inline void stfq_raw(void *ptr, double v)
{
CPU_DoubleU u;
u.d = v;
stl_raw(ptr, u.l.upper);
stl_raw(ptr + 4, u.l.lower);
}
#else
static inline int lduw(void *ptr)
static inline int lduw_raw(void *ptr)
{
return *(uint16_t *)ptr;
}
static inline int ldsw(void *ptr)
static inline int ldsw_raw(void *ptr)
{
return *(int16_t *)ptr;
}
static inline int ldl(void *ptr)
static inline int ldl_raw(void *ptr)
{
return *(uint32_t *)ptr;
}
static inline uint64_t ldq(void *ptr)
static inline uint64_t ldq_raw(void *ptr)
{
return *(uint64_t *)ptr;
}
static inline void stw(void *ptr, int v)
static inline void stw_raw(void *ptr, int v)
{
*(uint16_t *)ptr = v;
}
static inline void stl(void *ptr, int v)
static inline void stl_raw(void *ptr, int v)
{
*(uint32_t *)ptr = v;
}
static inline void stq(void *ptr, uint64_t v)
static inline void stq_raw(void *ptr, uint64_t v)
{
*(uint64_t *)ptr = v;
}
/* float access */
static inline float ldfl(void *ptr)
static inline float ldfl_raw(void *ptr)
{
return *(float *)ptr;
}
static inline double ldfq(void *ptr)
static inline double ldfq_raw(void *ptr)
{
return *(double *)ptr;
}
static inline void stfl(void *ptr, float v)
static inline void stfl_raw(void *ptr, float v)
{
*(float *)ptr = v;
}
static inline void stfq(void *ptr, double v)
static inline void stfq_raw(void *ptr, double v)
{
*(double *)ptr = v;
}
#endif
/* MMU memory access macros */
#if defined(CONFIG_USER_ONLY)
/* if user mode, no other memory access functions */
#define ldub(p) ldub_raw(p)
#define ldsb(p) ldsb_raw(p)
#define lduw(p) lduw_raw(p)
#define ldsw(p) ldsw_raw(p)
#define ldl(p) ldl_raw(p)
#define ldq(p) ldq_raw(p)
#define ldfl(p) ldfl_raw(p)
#define ldfq(p) ldfq_raw(p)
#define stb(p, v) stb_raw(p, v)
#define stw(p, v) stw_raw(p, v)
#define stl(p, v) stl_raw(p, v)
#define stq(p, v) stq_raw(p, v)
#define stfl(p, v) stfl_raw(p, v)
#define stfq(p, v) stfq_raw(p, v)
#define ldub_code(p) ldub_raw(p)
#define ldsb_code(p) ldsb_raw(p)
#define lduw_code(p) lduw_raw(p)
#define ldsw_code(p) ldsw_raw(p)
#define ldl_code(p) ldl_raw(p)
#define ldub_kernel(p) ldub_raw(p)
#define ldsb_kernel(p) ldsb_raw(p)
#define lduw_kernel(p) lduw_raw(p)
#define ldsw_kernel(p) ldsw_raw(p)
#define ldl_kernel(p) ldl_raw(p)
#define ldfl_kernel(p) ldfl_raw(p)
#define ldfq_kernel(p) ldfq_raw(p)
#define stb_kernel(p, v) stb_raw(p, v)
#define stw_kernel(p, v) stw_raw(p, v)
#define stl_kernel(p, v) stl_raw(p, v)
#define stq_kernel(p, v) stq_raw(p, v)
#define stfl_kernel(p, v) stfl_raw(p, v)
#define stfq_kernel(p, vt) stfq_raw(p, v)
#endif /* defined(CONFIG_USER_ONLY) */
/* page related stuff */
#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
extern unsigned long real_host_page_size;
extern unsigned long host_page_bits;
extern unsigned long host_page_size;
extern unsigned long host_page_mask;
extern unsigned long qemu_real_host_page_size;
extern unsigned long qemu_host_page_bits;
extern unsigned long qemu_host_page_size;
extern unsigned long qemu_host_page_mask;
#define HOST_PAGE_ALIGN(addr) (((addr) + host_page_size - 1) & host_page_mask)
#define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask)
/* same as PROT_xxx */
#define PAGE_READ 0x0001
@@ -284,8 +569,8 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size);
#define cpu_init cpu_x86_init
#define cpu_exec cpu_x86_exec
#define cpu_gen_code cpu_x86_gen_code
#define cpu_interrupt cpu_x86_interrupt
#define cpu_signal_handler cpu_x86_signal_handler
#define cpu_dump_state cpu_x86_dump_state
#elif defined(TARGET_ARM)
@@ -293,8 +578,26 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size);
#define cpu_init cpu_arm_init
#define cpu_exec cpu_arm_exec
#define cpu_gen_code cpu_arm_gen_code
#define cpu_interrupt cpu_arm_interrupt
#define cpu_signal_handler cpu_arm_signal_handler
#define cpu_dump_state cpu_arm_dump_state
#elif defined(TARGET_SPARC)
#define CPUState CPUSPARCState
#define cpu_init cpu_sparc_init
#define cpu_exec cpu_sparc_exec
#define cpu_gen_code cpu_sparc_gen_code
#define cpu_signal_handler cpu_sparc_signal_handler
#define cpu_dump_state cpu_sparc_dump_state
#elif defined(TARGET_PPC)
#define CPUState CPUPPCState
#define cpu_init cpu_ppc_init
#define cpu_exec cpu_ppc_exec
#define cpu_gen_code cpu_ppc_gen_code
#define cpu_signal_handler cpu_ppc_signal_handler
#define cpu_dump_state cpu_ppc_dump_state
#else
@@ -304,18 +607,119 @@ void page_unprotect_range(uint8_t *data, unsigned long data_size);
#endif /* SINGLE_CPU_DEFINES */
#define DEFAULT_GDBSTUB_PORT 1234
void cpu_abort(CPUState *env, const char *fmt, ...);
extern CPUState *cpu_single_env;
extern int code_copy_enabled;
#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */
#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */
#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
void cpu_interrupt(CPUState *s, int mask);
void cpu_reset_interrupt(CPUState *env, int mask);
/* gdb stub API */
extern int gdbstub_fd;
CPUState *cpu_gdbstub_get_env(void *opaque);
int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port);
int cpu_breakpoint_insert(CPUState *env, target_ulong pc);
int cpu_breakpoint_remove(CPUState *env, target_ulong pc);
void cpu_single_step(CPUState *env, int enabled);
void cpu_reset(CPUState *s);
/* Return the physical page corresponding to a virtual one. Use it
only for debugging because no protection checks are done. Return -1
if no page found. */
target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
#define CPU_LOG_TB_OUT_ASM (1 << 0)
#define CPU_LOG_TB_IN_ASM (1 << 1)
#define CPU_LOG_TB_OP (1 << 2)
#define CPU_LOG_TB_OP_OPT (1 << 3)
#define CPU_LOG_INT (1 << 4)
#define CPU_LOG_EXEC (1 << 5)
#define CPU_LOG_PCALL (1 << 6)
#define CPU_LOG_IOPORT (1 << 7)
#define CPU_LOG_TB_CPU (1 << 8)
/* define log items */
typedef struct CPULogItem {
int mask;
const char *name;
const char *help;
} CPULogItem;
extern CPULogItem cpu_log_items[];
void cpu_set_log(int log_flags);
void cpu_set_log_filename(const char *filename);
int cpu_str_to_log_mask(const char *str);
/* IO ports API */
/* NOTE: as these functions may be even used when there is an isa
brige on non x86 targets, we always defined them */
#ifndef NO_CPU_IO_DEFS
void cpu_outb(CPUState *env, int addr, int val);
void cpu_outw(CPUState *env, int addr, int val);
void cpu_outl(CPUState *env, int addr, int val);
int cpu_inb(CPUState *env, int addr);
int cpu_inw(CPUState *env, int addr);
int cpu_inl(CPUState *env, int addr);
#endif
/* memory API */
extern int phys_ram_size;
extern int phys_ram_fd;
extern uint8_t *phys_ram_base;
extern uint8_t *phys_ram_dirty;
/* physical memory access */
#define IO_MEM_NB_ENTRIES 256
#define TLB_INVALID_MASK (1 << 3)
#define IO_MEM_SHIFT 4
#define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */
#define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */
#define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT)
#define IO_MEM_CODE (3 << IO_MEM_SHIFT) /* used internally, never use directly */
#define IO_MEM_NOTDIRTY (4 << IO_MEM_SHIFT) /* used internally, never use directly */
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
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);
int cpu_register_io_memory(int io_index,
CPUReadMemoryFunc **mem_read,
CPUWriteMemoryFunc **mem_write,
void *opaque);
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
int len, int is_write);
static inline void cpu_physical_memory_read(target_phys_addr_t addr,
uint8_t *buf, int len)
{
cpu_physical_memory_rw(addr, buf, len, 0);
}
static inline void cpu_physical_memory_write(target_phys_addr_t addr,
const uint8_t *buf, int len)
{
cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1);
}
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
uint8_t *buf, int len, int is_write);
/* read dirty bit (return 0 or 1) */
static inline int cpu_physical_memory_is_dirty(target_ulong addr)
{
return phys_ram_dirty[addr >> TARGET_PAGE_BITS];
}
static inline void cpu_physical_memory_set_dirty(target_ulong addr)
{
phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 1;
}
void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end);
#endif /* CPU_ALL_H */

95
cpu-defs.h Normal file
View File

@@ -0,0 +1,95 @@
/*
* common defines for all CPUs
*
* Copyright (c) 2003 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 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
*/
#ifndef CPU_DEFS_H
#define CPU_DEFS_H
#include "config.h"
#include <setjmp.h>
#include <inttypes.h>
#include "osdep.h"
#ifndef TARGET_LONG_BITS
#error TARGET_LONG_BITS must be defined before including this header
#endif
#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
#define HOST_LONG_BITS 64
#else
#define HOST_LONG_BITS 32
#endif
#ifndef TARGET_PHYS_ADDR_BITS
#if TARGET_LONG_BITS >= HOST_LONG_BITS
#define TARGET_PHYS_ADDR_BITS TARGET_LONG_BITS
#else
#define TARGET_PHYS_ADDR_BITS HOST_LONG_BITS
#endif
#endif
#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
/* target_ulong is the type of a virtual address */
#if TARGET_LONG_SIZE == 4
typedef int32_t target_long;
typedef uint32_t target_ulong;
#elif TARGET_LONG_SIZE == 8
typedef int64_t target_long;
typedef uint64_t target_ulong;
#else
#error TARGET_LONG_SIZE undefined
#endif
/* target_phys_addr_t is the type of a physical address (its size can
be different from 'target_ulong'). We have sizeof(target_phys_addr)
= max(sizeof(unsigned long),
sizeof(size_of_target_physical_address)) because we must pass a
host pointer to memory operations in some cases */
#if TARGET_PHYS_ADDR_BITS == 32
typedef uint32_t target_phys_addr_t;
#elif TARGET_PHYS_ADDR_BITS == 64
typedef uint64_t target_phys_addr_t;
#else
#error TARGET_PHYS_ADDR_BITS undefined
#endif
#define HOST_LONG_SIZE (HOST_LONG_BITS / 8)
#define EXCP_INTERRUPT 256 /* async interruption */
#define EXCP_HLT 257 /* hlt instruction reached */
#define EXCP_DEBUG 258 /* cpu stopped after a breakpoint or singlestep */
#define MAX_BREAKPOINTS 32
#define CPU_TLB_SIZE 256
typedef struct CPUTLBEntry {
/* bit 31 to TARGET_PAGE_BITS : virtual address
bit TARGET_PAGE_BITS-1..IO_MEM_SHIFT : if non zero, memory io
zone number
bit 3 : indicates that the entry is invalid
bit 2..0 : zero
*/
target_ulong address;
/* addend to virtual address to get physical address */
target_phys_addr_t addend;
} CPUTLBEntry;
#endif

View File

@@ -18,19 +18,29 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#ifdef TARGET_I386
#include "exec-i386.h"
#endif
#ifdef TARGET_ARM
#include "exec-arm.h"
#include "exec.h"
#include "disas.h"
#if !defined(CONFIG_SOFTMMU)
#undef EAX
#undef ECX
#undef EDX
#undef EBX
#undef ESP
#undef EBP
#undef ESI
#undef EDI
#undef EIP
#include <signal.h>
#include <sys/ucontext.h>
#endif
#include "disas.h"
int tb_invalidated_flag;
//#define DEBUG_EXEC
//#define DEBUG_SIGNAL
#if defined(TARGET_ARM)
#if defined(TARGET_ARM) || defined(TARGET_SPARC)
/* XXX: unify with i386 target */
void cpu_loop_exit(void)
{
@@ -38,6 +48,28 @@ void cpu_loop_exit(void)
}
#endif
/* exit the current TB from a signal handler. The host registers are
restored in a state compatible with the CPU emulator
*/
void cpu_resume_from_signal(CPUState *env1, void *puc)
{
#if !defined(CONFIG_SOFTMMU)
struct ucontext *uc = puc;
#endif
env = env1;
/* XXX: restore cpu registers saved in host registers */
#if !defined(CONFIG_SOFTMMU)
if (puc) {
/* XXX: use siglongjmp ? */
sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
}
#endif
longjmp(env->jmp_env, 1);
}
/* main execution loop */
int cpu_exec(CPUState *env1)
@@ -136,6 +168,8 @@ int cpu_exec(CPUState *env1)
env->VF = (psr << 3) & 0x80000000;
env->cpsr = psr & ~0xf0000000;
}
#elif defined(TARGET_SPARC)
#elif defined(TARGET_PPC)
#else
#error unsupported target CPU
#endif
@@ -144,6 +178,7 @@ int cpu_exec(CPUState *env1)
/* prepare setjmp context for exception handling */
for(;;) {
if (setjmp(env->jmp_env) == 0) {
env->current_tb = NULL;
/* if an exception is pending, we execute it here */
if (env->exception_index >= 0) {
if (env->exception_index >= EXCP_INTERRUPT) {
@@ -170,7 +205,9 @@ int cpu_exec(CPUState *env1)
do_interrupt(env->exception_index,
env->exception_is_int,
env->error_code,
env->exception_next_eip);
env->exception_next_eip, 0);
#elif defined(TARGET_PPC)
do_interrupt(env);
#endif
}
env->exception_index = -1;
@@ -182,18 +219,19 @@ int cpu_exec(CPUState *env1)
tmp_T0 = T0;
#endif
interrupt_request = env->interrupt_request;
if (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) &&
(env->eflags & IF_MASK)) {
(env->eflags & IF_MASK) &&
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
int intno;
intno = cpu_x86_get_pic_interrupt(env);
if (loglevel) {
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
intno = cpu_get_pic_interrupt(env);
if (loglevel & CPU_LOG_TB_IN_ASM) {
fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
}
do_interrupt(intno, 0, 0, 0);
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
do_interrupt(intno, 0, 0, 0, 1);
/* ensure that no TB jump will be modified as
the program flow was changed */
#ifdef __sparc__
@@ -202,7 +240,38 @@ int cpu_exec(CPUState *env1)
T0 = 0;
#endif
}
#elif defined(TARGET_PPC)
#if 0
if ((interrupt_request & CPU_INTERRUPT_RESET)) {
cpu_ppc_reset(env);
}
#endif
if (msr_ee != 0) {
if ((interrupt_request & CPU_INTERRUPT_HARD)) {
/* Raise it */
env->exception_index = EXCP_EXTERNAL;
env->error_code = 0;
do_interrupt(env);
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
} else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
/* Raise it */
env->exception_index = EXCP_DECR;
env->error_code = 0;
do_interrupt(env);
env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
}
}
#endif
if (interrupt_request & CPU_INTERRUPT_EXITTB) {
env->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
/* ensure that no TB jump will be modified as
the program flow was changed */
#ifdef __sparc__
tmp_T0 = 0;
#else
T0 = 0;
#endif
}
if (interrupt_request & CPU_INTERRUPT_EXIT) {
env->interrupt_request &= ~CPU_INTERRUPT_EXIT;
env->exception_index = EXCP_INTERRUPT;
@@ -210,7 +279,7 @@ int cpu_exec(CPUState *env1)
}
}
#ifdef DEBUG_EXEC
if (loglevel) {
if (loglevel & CPU_LOG_EXEC) {
#if defined(TARGET_I386)
/* restore flags in standard format */
env->regs[R_EAX] = EAX;
@@ -228,48 +297,83 @@ int cpu_exec(CPUState *env1)
env->cpsr = compute_cpsr();
cpu_arm_dump_state(env, logfile, 0);
env->cpsr &= ~0xf0000000;
#elif defined(TARGET_SPARC)
cpu_sparc_dump_state (env, logfile, 0);
#elif defined(TARGET_PPC)
cpu_ppc_dump_state(env, logfile, 0);
#else
#error unsupported target CPU
#endif
}
#endif
/* we compute the CPU state. We assume it will not
change during the whole generated block. */
/* we record a subset of the CPU state. It will
always be the same before a given translated block
is executed. */
#if defined(TARGET_I386)
flags = (env->segs[R_CS].flags & DESC_B_MASK)
>> (DESC_B_SHIFT - GEN_FLAG_CODE32_SHIFT);
flags |= (env->segs[R_SS].flags & DESC_B_MASK)
>> (DESC_B_SHIFT - GEN_FLAG_SS32_SHIFT);
flags |= (((unsigned long)env->segs[R_DS].base |
(unsigned long)env->segs[R_ES].base |
(unsigned long)env->segs[R_SS].base) != 0) <<
GEN_FLAG_ADDSEG_SHIFT;
if (!(env->eflags & VM_MASK)) {
flags |= (env->segs[R_CS].selector & 3) << GEN_FLAG_CPL_SHIFT;
} else {
/* NOTE: a dummy CPL is kept */
flags |= (1 << GEN_FLAG_VM_SHIFT);
flags |= (3 << GEN_FLAG_CPL_SHIFT);
}
flags |= (env->eflags & (IOPL_MASK | TF_MASK));
flags = env->hflags;
flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
cs_base = env->segs[R_CS].base;
pc = cs_base + env->eip;
#elif defined(TARGET_ARM)
flags = 0;
cs_base = 0;
pc = (uint8_t *)env->regs[15];
#elif defined(TARGET_SPARC)
flags = 0;
cs_base = (uint8_t *)env->npc;
pc = (uint8_t *) env->pc;
#elif defined(TARGET_PPC)
flags = 0;
cs_base = 0;
pc = (uint8_t *)env->nip;
#else
#error unsupported CPU
#endif
tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base,
flags);
if (!tb) {
TranslationBlock **ptb1;
unsigned int h;
target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
spin_lock(&tb_lock);
tb_invalidated_flag = 0;
/* find translated block using physical mappings */
phys_pc = get_phys_addr_code(env, (unsigned long)pc);
phys_page1 = phys_pc & TARGET_PAGE_MASK;
phys_page2 = -1;
h = tb_phys_hash_func(phys_pc);
ptb1 = &tb_phys_hash[h];
for(;;) {
tb = *ptb1;
if (!tb)
goto not_found;
if (tb->pc == (unsigned long)pc &&
tb->page_addr[0] == phys_page1 &&
tb->cs_base == (unsigned long)cs_base &&
tb->flags == flags) {
/* check next page if needed */
if (tb->page_addr[1] != -1) {
virt_page2 = ((unsigned long)pc & TARGET_PAGE_MASK) +
TARGET_PAGE_SIZE;
phys_page2 = get_phys_addr_code(env, virt_page2);
if (tb->page_addr[1] == phys_page2)
goto found;
} else {
goto found;
}
}
ptb1 = &tb->phys_hash_next;
}
not_found:
/* if no translated code available, then translate it now */
tb = tb_alloc((unsigned long)pc);
if (!tb) {
/* flush must be done */
tb_flush();
tb_flush(env);
/* cannot fail at this point */
tb = tb_alloc((unsigned long)pc);
/* don't forget to invalidate previous TB info */
@@ -280,25 +384,35 @@ int cpu_exec(CPUState *env1)
tb->tc_ptr = tc_ptr;
tb->cs_base = (unsigned long)cs_base;
tb->flags = flags;
ret = cpu_gen_code(tb, CODE_GEN_MAX_SIZE, &code_gen_size);
#if defined(TARGET_I386)
/* XXX: suppress that, this is incorrect */
/* if invalid instruction, signal it */
if (ret != 0) {
/* NOTE: the tb is allocated but not linked, so we
can leave it */
spin_unlock(&tb_lock);
raise_exception(EXCP06_ILLOP);
cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
/* check next page if needed */
virt_page2 = ((unsigned long)pc + tb->size - 1) & TARGET_PAGE_MASK;
phys_page2 = -1;
if (((unsigned long)pc & TARGET_PAGE_MASK) != virt_page2) {
phys_page2 = get_phys_addr_code(env, virt_page2);
}
#endif
tb_link_phys(tb, phys_pc, phys_page2);
found:
if (tb_invalidated_flag) {
/* as some TB could have been invalidated because
of memory exceptions while generating the code, we
must recompute the hash index here */
ptb = &tb_hash[tb_hash_func((unsigned long)pc)];
while (*ptb != NULL)
ptb = &(*ptb)->hash_next;
T0 = 0;
}
/* we add the TB in the virtual pc hash table */
*ptb = tb;
tb->hash_next = NULL;
tb_link(tb);
code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
spin_unlock(&tb_lock);
}
#ifdef DEBUG_EXEC
if (loglevel) {
if (loglevel & CPU_LOG_EXEC) {
fprintf(logfile, "Trace 0x%08lx [0x%08lx] %s\n",
(long)tb->tc_ptr, (long)tb->pc,
lookup_symbol((void *)tb->pc));
@@ -307,14 +421,20 @@ int cpu_exec(CPUState *env1)
#ifdef __sparc__
T0 = tmp_T0;
#endif
/* see if we can patch the calling TB. XXX: remove TF test */
/* see if we can patch the calling TB. */
if (T0 != 0
#if defined(TARGET_I386)
&& !(env->eflags & TF_MASK)
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
&& (tb->cflags & CF_CODE_COPY) ==
(((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
#endif
) {
spin_lock(&tb_lock);
tb_add_jump((TranslationBlock *)(T0 & ~3), T0 & 3, tb);
#if defined(USE_CODE_COPY)
/* propagates the FP use info */
((TranslationBlock *)(T0 & ~3))->cflags |=
(tb->cflags & CF_FP_USED);
#endif
spin_unlock(&tb_lock);
}
tc_ptr = tb->tc_ptr;
@@ -334,10 +454,93 @@ int cpu_exec(CPUState *env1)
: /* no outputs */
: "r" (gen_func)
: "r1", "r2", "r3", "r8", "r9", "r10", "r12", "r14");
#elif defined(TARGET_I386) && defined(USE_CODE_COPY)
{
if (!(tb->cflags & CF_CODE_COPY)) {
if ((tb->cflags & CF_FP_USED) && env->native_fp_regs) {
save_native_fp_state(env);
}
gen_func();
} else {
if ((tb->cflags & CF_FP_USED) && !env->native_fp_regs) {
restore_native_fp_state(env);
}
/* we work with native eflags */
CC_SRC = cc_table[CC_OP].compute_all();
CC_OP = CC_OP_EFLAGS;
asm(".globl exec_loop\n"
"\n"
"debug1:\n"
" pushl %%ebp\n"
" fs movl %10, %9\n"
" fs movl %11, %%eax\n"
" andl $0x400, %%eax\n"
" fs orl %8, %%eax\n"
" pushl %%eax\n"
" popf\n"
" fs movl %%esp, %12\n"
" fs movl %0, %%eax\n"
" fs movl %1, %%ecx\n"
" fs movl %2, %%edx\n"
" fs movl %3, %%ebx\n"
" fs movl %4, %%esp\n"
" fs movl %5, %%ebp\n"
" fs movl %6, %%esi\n"
" fs movl %7, %%edi\n"
" fs jmp *%9\n"
"exec_loop:\n"
" fs movl %%esp, %4\n"
" fs movl %12, %%esp\n"
" fs movl %%eax, %0\n"
" fs movl %%ecx, %1\n"
" fs movl %%edx, %2\n"
" fs movl %%ebx, %3\n"
" fs movl %%ebp, %5\n"
" fs movl %%esi, %6\n"
" fs movl %%edi, %7\n"
" pushf\n"
" popl %%eax\n"
" movl %%eax, %%ecx\n"
" andl $0x400, %%ecx\n"
" shrl $9, %%ecx\n"
" andl $0x8d5, %%eax\n"
" fs movl %%eax, %8\n"
" movl $1, %%eax\n"
" subl %%ecx, %%eax\n"
" fs movl %%eax, %11\n"
" fs movl %9, %%ebx\n" /* get T0 value */
" popl %%ebp\n"
:
: "m" (*(uint8_t *)offsetof(CPUState, regs[0])),
"m" (*(uint8_t *)offsetof(CPUState, regs[1])),
"m" (*(uint8_t *)offsetof(CPUState, regs[2])),
"m" (*(uint8_t *)offsetof(CPUState, regs[3])),
"m" (*(uint8_t *)offsetof(CPUState, regs[4])),
"m" (*(uint8_t *)offsetof(CPUState, regs[5])),
"m" (*(uint8_t *)offsetof(CPUState, regs[6])),
"m" (*(uint8_t *)offsetof(CPUState, regs[7])),
"m" (*(uint8_t *)offsetof(CPUState, cc_src)),
"m" (*(uint8_t *)offsetof(CPUState, tmp0)),
"a" (gen_func),
"m" (*(uint8_t *)offsetof(CPUState, df)),
"m" (*(uint8_t *)offsetof(CPUState, saved_esp))
: "%ecx", "%edx"
);
}
}
#else
gen_func();
#endif
env->current_tb = NULL;
/* reset soft MMU for next block (it can currently
only be set by a memory fault) */
#if defined(TARGET_I386) && !defined(CONFIG_SOFTMMU)
if (env->hflags & HF_SOFTMMU_MASK) {
env->hflags &= ~HF_SOFTMMU_MASK;
/* do not allow linking to another block */
T0 = 0;
}
#endif
}
} else {
}
@@ -345,6 +548,11 @@ int cpu_exec(CPUState *env1)
#if defined(TARGET_I386)
#if defined(USE_CODE_COPY)
if (env->native_fp_regs) {
save_native_fp_state(env);
}
#endif
/* restore flags in standard format */
env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
@@ -375,6 +583,8 @@ int cpu_exec(CPUState *env1)
#endif
#elif defined(TARGET_ARM)
env->cpsr = compute_cpsr();
#elif defined(TARGET_SPARC)
#elif defined(TARGET_PPC)
#else
#error unsupported target CPU
#endif
@@ -388,7 +598,20 @@ int cpu_exec(CPUState *env1)
return ret;
}
#if defined(TARGET_I386)
/* must only be called from the generated code as an exception can be
generated */
void tb_invalidate_page_range(target_ulong start, target_ulong end)
{
/* XXX: cannot enable it yet because it yields to MMU exception
where NIP != read address on PowerPC */
#if 0
target_ulong phys_addr;
phys_addr = get_phys_addr_code(env, start);
tb_invalidate_phys_page_range(phys_addr, phys_addr + end - start, 0);
#endif
}
#if defined(TARGET_I386) && defined(CONFIG_USER_ONLY)
void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
{
@@ -396,18 +619,12 @@ void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
saved_env = env;
env = s;
if (env->eflags & VM_MASK) {
SegmentCache *sc;
if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
selector &= 0xffff;
sc = &env->segs[seg_reg];
/* NOTE: in VM86 mode, limit and flags are never reloaded,
so we must load them here */
sc->base = (void *)(selector << 4);
sc->limit = 0xffff;
sc->flags = 0;
sc->selector = selector;
cpu_x86_load_seg_cache(env, seg_reg, selector,
(uint8_t *)(selector << 4), 0xffff, 0);
} else {
load_seg(seg_reg, selector, 0);
load_seg(seg_reg, selector);
}
env = saved_env;
}
@@ -438,17 +655,7 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
#endif /* TARGET_I386 */
#undef EAX
#undef ECX
#undef EDX
#undef EBX
#undef ESP
#undef EBP
#undef ESI
#undef EDI
#undef EIP
#include <signal.h>
#include <sys/ucontext.h>
#if !defined(CONFIG_SOFTMMU)
#if defined(TARGET_I386)
@@ -457,7 +664,8 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
write caused the exception and otherwise 0'. 'old_set' is the
signal set which should be restored */
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
int is_write, sigset_t *old_set)
int is_write, sigset_t *old_set,
void *puc)
{
TranslationBlock *tb;
int ret;
@@ -465,15 +673,17 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
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);
qemu_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)) {
if (is_write && page_unprotect(address, pc, puc)) {
return 1;
}
/* see if it is an MMU fault */
ret = cpu_x86_handle_mmu_fault(env, address, is_write);
ret = cpu_x86_handle_mmu_fault(env, address, is_write,
((env->hflags & HF_CPL_MASK) == 3), 0);
if (ret < 0)
return 0; /* not an MMU fault */
if (ret == 0)
@@ -483,39 +693,129 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
if (tb) {
/* the PC is inside the translated code. It means that we have
a virtual CPU fault */
cpu_restore_state(tb, env, pc);
cpu_restore_state(tb, env, pc, puc);
}
if (ret == 1) {
#if 0
printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
env->eip, env->cr[2], env->error_code);
printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
env->eip, env->cr[2], env->error_code);
#endif
/* we restore the process signal mask as the sigreturn should
do it (XXX: use sigsetjmp) */
sigprocmask(SIG_SETMASK, old_set, NULL);
raise_exception_err(EXCP0E_PAGE, env->error_code);
/* we restore the process signal mask as the sigreturn should
do it (XXX: use sigsetjmp) */
sigprocmask(SIG_SETMASK, old_set, NULL);
raise_exception_err(EXCP0E_PAGE, env->error_code);
} else {
/* activate soft MMU for this block */
env->hflags |= HF_SOFTMMU_MASK;
cpu_resume_from_signal(env, puc);
}
/* never comes here */
return 1;
}
#elif defined(TARGET_ARM)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
int is_write, sigset_t *old_set)
int is_write, sigset_t *old_set,
void *puc)
{
/* XXX: do more */
return 0;
}
#elif defined(TARGET_SPARC)
static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
int is_write, sigset_t *old_set,
void *puc)
{
/* XXX: locking issue */
if (is_write && page_unprotect(address, pc, puc)) {
return 1;
}
return 0;
}
#elif defined (TARGET_PPC)
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 1
if (cpu_single_env)
env = cpu_single_env; /* XXX: find a correct solution for multithread */
#endif
#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_ppc_handle_mmu_fault(env, address, is_write, msr_pr, 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);
}
if (ret == 1) {
#if 0
printf("PF exception: NIP=0x%08x error=0x%x %p\n",
env->nip, env->error_code, tb);
#endif
/* we restore the process signal mask as the sigreturn should
do it (XXX: use sigsetjmp) */
sigprocmask(SIG_SETMASK, old_set, NULL);
do_raise_exception_err(env->exception_index, env->error_code);
} else {
/* activate soft MMU for this block */
cpu_resume_from_signal(env, puc);
}
/* never comes here */
return 1;
}
#else
#error unsupported target CPU
#endif
#if defined(__i386__)
#if defined(USE_CODE_COPY)
static void cpu_send_trap(unsigned long pc, int trap,
struct ucontext *uc)
{
TranslationBlock *tb;
if (cpu_single_env)
env = cpu_single_env; /* XXX: find a correct solution for multithread */
/* 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, uc);
}
sigprocmask(SIG_SETMASK, &uc->uc_sigmask, NULL);
raise_exception_err(trap, env->error_code);
}
#endif
int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc)
{
struct ucontext *uc = puc;
unsigned long pc;
int trapno;
#ifndef REG_EIP
/* for glibc 2.1 */
#define REG_EIP EIP
@@ -523,34 +823,105 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
#define REG_TRAPNO TRAPNO
#endif
pc = uc->uc_mcontext.gregs[REG_EIP];
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
(uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
&uc->uc_sigmask);
trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
if (trapno == 0x00 || trapno == 0x05) {
/* send division by zero or bound exception */
cpu_send_trap(pc, trapno, uc);
return 1;
} else
#endif
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
trapno == 0xe ?
(uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
&uc->uc_sigmask, puc);
}
#elif defined(__powerpc)
#elif defined(__x86_64__)
int cpu_signal_handler(int host_signum, struct siginfo *info,
int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc)
{
struct ucontext *uc = puc;
unsigned long pc;
pc = uc->uc_mcontext.gregs[REG_RIP];
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
(uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
&uc->uc_sigmask, puc);
}
#elif defined(__powerpc__)
/***********************************************************************
* signal context platform-specific definitions
* From Wine
*/
#ifdef linux
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext.regs->reg_name)
/* Gpr Registers access */
# define GPR_sig(reg_num, context) REG_sig(gpr[reg_num], context)
# define IAR_sig(context) REG_sig(nip, context) /* Program counter */
# define MSR_sig(context) REG_sig(msr, context) /* Machine State Register (Supervisor) */
# define CTR_sig(context) REG_sig(ctr, context) /* Count register */
# define XER_sig(context) REG_sig(xer, context) /* User's integer exception register */
# define LR_sig(context) REG_sig(link, context) /* Link register */
# define CR_sig(context) REG_sig(ccr, context) /* Condition register */
/* Float Registers access */
# define FLOAT_sig(reg_num, context) (((double*)((char*)((context)->uc_mcontext.regs+48*4)))[reg_num])
# define FPSCR_sig(context) (*(int*)((char*)((context)->uc_mcontext.regs+(48+32*2)*4)))
/* Exception Registers access */
# define DAR_sig(context) REG_sig(dar, context)
# define DSISR_sig(context) REG_sig(dsisr, context)
# define TRAP_sig(context) REG_sig(trap, context)
#endif /* linux */
#ifdef __APPLE__
# include <sys/ucontext.h>
typedef struct ucontext SIGCONTEXT;
/* All Registers access - only for local access */
# define REG_sig(reg_name, context) ((context)->uc_mcontext->ss.reg_name)
# define FLOATREG_sig(reg_name, context) ((context)->uc_mcontext->fs.reg_name)
# define EXCEPREG_sig(reg_name, context) ((context)->uc_mcontext->es.reg_name)
# define VECREG_sig(reg_name, context) ((context)->uc_mcontext->vs.reg_name)
/* Gpr Registers access */
# define GPR_sig(reg_num, context) REG_sig(r##reg_num, context)
# define IAR_sig(context) REG_sig(srr0, context) /* Program counter */
# define MSR_sig(context) REG_sig(srr1, context) /* Machine State Register (Supervisor) */
# define CTR_sig(context) REG_sig(ctr, context)
# define XER_sig(context) REG_sig(xer, context) /* Link register */
# define LR_sig(context) REG_sig(lr, context) /* User's integer exception register */
# define CR_sig(context) REG_sig(cr, context) /* Condition register */
/* Float Registers access */
# define FLOAT_sig(reg_num, context) FLOATREG_sig(fpregs[reg_num], context)
# define FPSCR_sig(context) ((double)FLOATREG_sig(fpscr, context))
/* Exception Registers access */
# define DAR_sig(context) EXCEPREG_sig(dar, context) /* Fault registers for coredump */
# define DSISR_sig(context) EXCEPREG_sig(dsisr, context)
# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
#endif /* __APPLE__ */
int cpu_signal_handler(int host_signum, siginfo *info,
void *puc)
{
struct ucontext *uc = puc;
struct pt_regs *regs = uc->uc_mcontext.regs;
unsigned long pc;
int is_write;
pc = regs->nip;
pc = IAR_sig(uc);
is_write = 0;
#if 0
/* ppc 4xx case */
if (regs->dsisr & 0x00800000)
if (DSISR_sig(uc) & 0x00800000)
is_write = 1;
#else
if (regs->trap != 0x400 && (regs->dsisr & 0x02000000))
if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
is_write = 1;
#endif
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, &uc->uc_sigmask);
is_write, &uc->uc_sigmask, puc);
}
#elif defined(__alpha__)
@@ -580,7 +951,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
}
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, &uc->uc_sigmask);
is_write, &uc->uc_sigmask, puc);
}
#elif defined(__sparc__)
@@ -612,7 +983,7 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
}
}
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, sigmask);
is_write, sigmask, NULL);
}
#elif defined(__arm__)
@@ -632,8 +1003,27 @@ int cpu_signal_handler(int host_signum, struct siginfo *info,
&uc->uc_sigmask);
}
#elif defined(__mc68000)
int cpu_signal_handler(int host_signum, struct siginfo *info,
void *puc)
{
struct ucontext *uc = puc;
unsigned long pc;
int is_write;
pc = uc->uc_mcontext.gregs[16];
/* XXX: compute is_write */
is_write = 0;
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write,
&uc->uc_sigmask, puc);
}
#else
#error host CPU specific signal handler needed
#endif
#endif /* !defined(CONFIG_SOFTMMU) */

View File

@@ -16,7 +16,9 @@
#define PARAMS(x) x
typedef void *PTR;
typedef uint64_t bfd_vma;
typedef int64_t bfd_signed_vma;
typedef uint8_t bfd_byte;
#define sprintf_vma(s,x) sprintf (s, "%0" PRIx64, x)
enum bfd_flavour {
bfd_target_unknown_flavour,
@@ -105,6 +107,9 @@ enum bfd_architecture
bfd_arch_i386, /* Intel 386 */
#define bfd_mach_i386_i386 0
#define bfd_mach_i386_i8086 1
#define bfd_mach_i386_i386_intel_syntax 2
#define bfd_mach_x86_64 3
#define bfd_mach_x86_64_intel_syntax 4
bfd_arch_we32k, /* AT&T WE32xxx */
bfd_arch_tahoe, /* CCI/Harris Tahoe */
bfd_arch_i860, /* Intel 860 */

118
disas.c
View File

@@ -1,10 +1,13 @@
/* General "disassemble this chunk" code. Used for debugging. */
#include "config.h"
#include "dis-asm.h"
#include "disas.h"
#include "elf.h"
#include <errno.h>
#include "cpu.h"
#include "exec-all.h"
#include "disas.h"
/* Filled in by elfload.c. Simplistic, but will do for now. */
unsigned int disas_num_syms;
void *disas_symtab;
@@ -19,14 +22,32 @@ buffer_read_memory (memaddr, myaddr, length, info)
int length;
struct disassemble_info *info;
{
if (memaddr < info->buffer_vma
|| memaddr + length > info->buffer_vma + info->buffer_length)
/* Out of bounds. Use EIO because GDB uses it. */
return EIO;
memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
return 0;
if (memaddr < info->buffer_vma
|| memaddr + length > info->buffer_vma + info->buffer_length)
/* Out of bounds. Use EIO because GDB uses it. */
return EIO;
memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
return 0;
}
#if !defined(CONFIG_USER_ONLY)
/* Get LENGTH bytes from info's buffer, at target address memaddr.
Transfer them to myaddr. */
static int
target_read_memory (memaddr, myaddr, length, info)
bfd_vma memaddr;
bfd_byte *myaddr;
int length;
struct disassemble_info *info;
{
int i;
for(i = 0; i < length; i++) {
myaddr[i] = ldub_code((void *)((long)memaddr + i));
}
return 0;
}
#endif
/* Print an error message. We can assume that this is in response to
an error return from buffer_read_memory. */
void
@@ -103,6 +124,12 @@ void disas(FILE *out, void *code, unsigned long size, int is_host, int flags)
INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
#if !defined(CONFIG_USER_ONLY)
if (!is_host) {
disasm_info.read_memory_func = target_read_memory;
}
#endif
disasm_info.buffer = code;
disasm_info.buffer_vma = (unsigned long)code;
disasm_info.buffer_length = size;
@@ -113,9 +140,12 @@ void disas(FILE *out, void *code, unsigned long size, int is_host, int flags)
#else
disasm_info.endian = BFD_ENDIAN_LITTLE;
#endif
#ifdef __i386__
#if defined(__i386__)
disasm_info.mach = bfd_mach_i386_i386;
print_insn = print_insn_i386;
#elif defined(__x86_64__)
disasm_info.mach = bfd_mach_x86_64;
print_insn = print_insn_i386;
#elif defined(__powerpc__)
print_insn = print_insn_ppc;
#elif defined(__alpha__)
@@ -142,6 +172,10 @@ void disas(FILE *out, void *code, unsigned long size, int is_host, int flags)
print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
print_insn = print_insn_arm;
#elif defined(TARGET_SPARC)
print_insn = print_insn_sparc;
#elif defined(TARGET_PPC)
print_insn = print_insn_ppc;
#else
fprintf(out, "Asm output not supported on this arch\n");
return;
@@ -185,3 +219,71 @@ const char *lookup_symbol(void *orig_addr)
}
return "";
}
#if !defined(CONFIG_USER_ONLY)
static int monitor_disas_is_physical;
static int
monitor_read_memory (memaddr, myaddr, length, info)
bfd_vma memaddr;
bfd_byte *myaddr;
int length;
struct disassemble_info *info;
{
if (monitor_disas_is_physical) {
cpu_physical_memory_rw(memaddr, myaddr, length, 0);
} else {
cpu_memory_rw_debug(cpu_single_env, memaddr,myaddr, length, 0);
}
return 0;
}
void monitor_disas(target_ulong pc, int nb_insn, int is_physical, int flags)
{
FILE *out;
int count, i;
struct disassemble_info disasm_info;
int (*print_insn)(bfd_vma pc, disassemble_info *info);
out = stdout;
INIT_DISASSEMBLE_INFO(disasm_info, out, fprintf);
monitor_disas_is_physical = is_physical;
disasm_info.read_memory_func = monitor_read_memory;
disasm_info.buffer_vma = pc;
#ifdef TARGET_WORDS_BIGENDIAN
disasm_info.endian = BFD_ENDIAN_BIG;
#else
disasm_info.endian = BFD_ENDIAN_LITTLE;
#endif
#if defined(TARGET_I386)
if (!flags)
disasm_info.mach = bfd_mach_i386_i386;
else
disasm_info.mach = bfd_mach_i386_i8086;
print_insn = print_insn_i386;
#elif defined(TARGET_ARM)
print_insn = print_insn_arm;
#elif defined(TARGET_SPARC)
print_insn = print_insn_sparc;
#elif defined(TARGET_PPC)
print_insn = print_insn_ppc;
#else
fprintf(out, "Asm output not supported on this arch\n");
return;
#endif
for(i = 0; i < nb_insn; i++) {
fprintf(out, "0x%08lx: ", (unsigned long)pc);
count = print_insn(pc, &disasm_info);
fprintf(out, "\n");
if (count < 0)
break;
pc += count;
}
}
#endif

View File

@@ -3,6 +3,7 @@
/* Disassemble this for me please... (debugging). */
void disas(FILE *out, void *code, unsigned long size, int is_host, int flags);
void monitor_disas(target_ulong pc, int nb_insn, int is_physical, int flags);
/* Look up symbol for debugging purpose. Returns "" if unknown. */
const char *lookup_symbol(void *orig_addr);

View File

@@ -17,31 +17,62 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#if !defined(__DYNGEN_EXEC_H__)
#define __DYNGEN_EXEC_H__
/* NOTE: standard headers should be used with special care at this
point because host CPU registers are used as global variables. Some
host headers do not allow that. */
#include <stddef.h>
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
/* XXX may be done for all 64 bits targets ? */
#if defined (__x86_64__)
typedef unsigned long uint64_t;
#else
typedef unsigned long long uint64_t;
#endif
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
#if defined (__x86_64__)
typedef signed long int64_t;
#else
typedef signed long long int64_t;
#endif
#define bswap32(x) \
({ \
uint32_t __x = (x); \
((uint32_t)( \
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
})
#define INT8_MIN (-128)
#define INT16_MIN (-32767-1)
#define INT32_MIN (-2147483647-1)
#define INT64_MIN (-(int64_t)(9223372036854775807)-1)
#define INT8_MAX (127)
#define INT16_MAX (32767)
#define INT32_MAX (2147483647)
#define INT64_MAX ((int64_t)(9223372036854775807))
#define UINT8_MAX (255)
#define UINT16_MAX (65535)
#define UINT32_MAX (4294967295U)
#define UINT64_MAX ((uint64_t)(18446744073709551615))
typedef struct FILE FILE;
extern int fprintf(FILE *, const char *, ...);
extern int printf(const char *, ...);
#undef NULL
#define NULL 0
#if defined(_BSD) && !defined(__APPLE__)
#include <ieeefp.h>
#define FE_TONEAREST FP_RN
#define FE_DOWNWARD FP_RM
#define FE_UPWARD FP_RP
#define FE_TOWARDZERO FP_RZ
#define fesetround(x) fpsetround(x)
#else
#include <fenv.h>
#endif
#ifdef __i386__
#define AREG0 "ebp"
@@ -49,11 +80,21 @@ extern int printf(const char *, ...);
#define AREG2 "esi"
#define AREG3 "edi"
#endif
#ifdef __x86_64__
#define AREG0 "rbp"
#define AREG1 "rbx"
#define AREG2 "r12"
#define AREG3 "r13"
#define AREG4 "r14"
#define AREG5 "r15"
#endif
#ifdef __powerpc__
#define AREG0 "r27"
#define AREG1 "r24"
#define AREG2 "r25"
#define AREG3 "r26"
/* XXX: suppress this hack */
#if defined(CONFIG_USER_ONLY)
#define AREG4 "r16"
#define AREG5 "r17"
#define AREG6 "r18"
@@ -62,6 +103,7 @@ extern int printf(const char *, ...);
#define AREG9 "r21"
#define AREG10 "r22"
#define AREG11 "r23"
#endif
#define USE_INT_TO_FLOAT_HELPERS
#define BUGGY_GCC_DIV64
#endif
@@ -109,6 +151,13 @@ extern int printf(const char *, ...);
#define AREG5 "$13"
#define AREG6 "$14"
#endif
#ifdef __mc68000
#define AREG0 "%a5"
#define AREG1 "%a4"
#define AREG2 "%d7"
#define AREG3 "%d6"
#define AREG4 "%d5"
#endif
#ifdef __ia64__
#define AREG0 "r27"
#define AREG1 "r24"
@@ -154,11 +203,14 @@ extern int __op_param1, __op_param2, __op_param3;
#define PARAM3 ((long)(&__op_param3))
#endif
extern int __op_jmp0, __op_jmp1;
extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
#ifdef __i386__
#define EXIT_TB() asm volatile ("ret")
#endif
#ifdef __x86_64__
#define EXIT_TB() asm volatile ("ret")
#endif
#ifdef __powerpc__
#define EXIT_TB() asm volatile ("blr")
#endif
@@ -178,4 +230,8 @@ extern int __op_jmp0, __op_jmp1;
#ifdef __arm__
#define EXIT_TB() asm volatile ("b exec_loop")
#endif
#ifdef __mc68000
#define EXIT_TB() asm volatile ("rts")
#endif
#endif /* !defined(__DYNGEN_EXEC_H__) */

1734
dyngen.c

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@
*/
int __op_param1, __op_param2, __op_param3;
int __op_jmp0, __op_jmp1;
int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
#ifdef __i386__
static inline void flush_icache_range(unsigned long start, unsigned long stop)
@@ -27,6 +27,12 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop)
}
#endif
#ifdef __x86_64__
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
}
#endif
#ifdef __s390__
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
@@ -94,6 +100,14 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop)
}
#endif
#ifdef __mc68000
#include <asm/cachectl.h>
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
cacheflush(start,FLUSH_SCOPE_LINE,FLUSH_CACHE_BOTH,stop-start+16);
}
#endif
#ifdef __alpha__
register int gp asm("$29");

603
exec-all.h Normal file
View File

@@ -0,0 +1,603 @@
/*
* internal execution defines for qemu
*
* Copyright (c) 2003 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 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
*/
/* allow to see translation results - the slowdown should be negligible, so we leave it */
#define DEBUG_DISAS
#ifndef glue
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
#define stringify(s) tostring(s)
#define tostring(s) #s
#endif
#if GCC_MAJOR < 3
#define __builtin_expect(x, n) (x)
#endif
#ifdef __i386__
#define REGPARM(n) __attribute((regparm(n)))
#else
#define REGPARM(n)
#endif
/* is_jmp field values */
#define DISAS_NEXT 0 /* next instruction can be analyzed */
#define DISAS_JUMP 1 /* only pc was modified dynamically */
#define DISAS_UPDATE 2 /* cpu state was modified dynamically */
#define DISAS_TB_JUMP 3 /* only pc was modified statically */
struct TranslationBlock;
/* XXX: make safe guess about sizes */
#define MAX_OP_PER_INSTR 32
#define OPC_BUF_SIZE 512
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
extern uint16_t gen_opc_buf[OPC_BUF_SIZE];
extern uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
extern uint32_t gen_opc_pc[OPC_BUF_SIZE];
extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
typedef void (GenOpFunc)(void);
typedef void (GenOpFunc1)(long);
typedef void (GenOpFunc2)(long, long);
typedef void (GenOpFunc3)(long, long, long);
#if defined(TARGET_I386)
void optimize_flags_init(void);
#endif
extern FILE *logfile;
extern int loglevel;
int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf);
int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
int max_code_size, int *gen_code_size_ptr);
int cpu_restore_state(struct TranslationBlock *tb,
CPUState *env, unsigned long searched_pc,
void *puc);
int cpu_gen_code_copy(CPUState *env, struct TranslationBlock *tb,
int max_code_size, int *gen_code_size_ptr);
int cpu_restore_state_copy(struct TranslationBlock *tb,
CPUState *env, unsigned long searched_pc,
void *puc);
void cpu_resume_from_signal(CPUState *env1, void *puc);
void cpu_exec_init(void);
int page_unprotect(unsigned long address, unsigned long pc, void *puc);
void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
int is_cpu_write_access);
void tb_invalidate_page_range(target_ulong start, target_ulong end);
void tlb_flush_page(CPUState *env, target_ulong addr);
void tlb_flush(CPUState *env, int flush_global);
int tlb_set_page(CPUState *env, target_ulong vaddr,
target_phys_addr_t paddr, int prot,
int is_user, int is_softmmu);
#define CODE_GEN_MAX_SIZE 65536
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
#define CODE_GEN_HASH_BITS 15
#define CODE_GEN_HASH_SIZE (1 << CODE_GEN_HASH_BITS)
#define CODE_GEN_PHYS_HASH_BITS 15
#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS)
/* maximum total translate dcode allocated */
/* NOTE: the translated code area cannot be too big because on some
archs the range of "fast" function calls is limited. Here is a
summary of the ranges:
i386 : signed 32 bits
arm : signed 26 bits
ppc : signed 24 bits
sparc : signed 32 bits
alpha : signed 23 bits
*/
#if defined(__alpha__)
#define CODE_GEN_BUFFER_SIZE (2 * 1024 * 1024)
#elif defined(__powerpc__)
#define CODE_GEN_BUFFER_SIZE (6 * 1024 * 1024)
#else
#define CODE_GEN_BUFFER_SIZE (8 * 1024 * 1024)
#endif
//#define CODE_GEN_BUFFER_SIZE (128 * 1024)
/* estimated block size for TB allocation */
/* XXX: use a per code average code fragment size and modulate it
according to the host CPU */
#if defined(CONFIG_SOFTMMU)
#define CODE_GEN_AVG_BLOCK_SIZE 128
#else
#define CODE_GEN_AVG_BLOCK_SIZE 64
#endif
#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE)
#if defined(__powerpc__)
#define USE_DIRECT_JUMP
#endif
#if defined(__i386__) && !defined(_WIN32)
#define USE_DIRECT_JUMP
#endif
typedef struct TranslationBlock {
target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
target_ulong cs_base; /* CS base for this block */
unsigned int flags; /* flags defining in which context the code was generated */
uint16_t size; /* size of target code for this block (1 <=
size <= TARGET_PAGE_SIZE) */
uint16_t cflags; /* compile flags */
#define CF_CODE_COPY 0x0001 /* block was generated in code copy mode */
#define CF_TB_FP_USED 0x0002 /* fp ops are used in the TB */
#define CF_FP_USED 0x0004 /* fp ops are used in the TB or in a chained TB */
#define CF_SINGLE_INSN 0x0008 /* compile only a single instruction */
uint8_t *tc_ptr; /* pointer to the translated code */
struct TranslationBlock *hash_next; /* next matching tb for virtual address */
/* next matching tb for physical address. */
struct TranslationBlock *phys_hash_next;
/* first and second physical page containing code. The lower bit
of the pointer tells the index in page_next[] */
struct TranslationBlock *page_next[2];
target_ulong page_addr[2];
/* the following data are used to directly call another TB from
the code of this one. */
uint16_t tb_next_offset[2]; /* offset of original jump target */
#ifdef USE_DIRECT_JUMP
uint16_t tb_jmp_offset[4]; /* offset of jump instruction */
#else
uint32_t tb_next[2]; /* address of jump generated code */
#endif
/* list of TBs jumping to this one. This is a circular list using
the two least significant bits of the pointers to tell what is
the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 =
jmp_first */
struct TranslationBlock *jmp_next[2];
struct TranslationBlock *jmp_first;
} TranslationBlock;
static inline unsigned int tb_hash_func(unsigned long pc)
{
return pc & (CODE_GEN_HASH_SIZE - 1);
}
static inline unsigned int tb_phys_hash_func(unsigned long pc)
{
return pc & (CODE_GEN_PHYS_HASH_SIZE - 1);
}
TranslationBlock *tb_alloc(unsigned long pc);
void tb_flush(CPUState *env);
void tb_link(TranslationBlock *tb);
void tb_link_phys(TranslationBlock *tb,
target_ulong phys_pc, target_ulong phys_page2);
extern TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
extern uint8_t *code_gen_ptr;
/* find a translation block in the translation cache. If not found,
return NULL and the pointer to the last element of the list in pptb */
static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
target_ulong pc,
target_ulong cs_base,
unsigned int flags)
{
TranslationBlock **ptb, *tb;
unsigned int h;
h = tb_hash_func(pc);
ptb = &tb_hash[h];
for(;;) {
tb = *ptb;
if (!tb)
break;
if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
return tb;
ptb = &tb->hash_next;
}
*pptb = ptb;
return NULL;
}
#if defined(USE_DIRECT_JUMP)
#if defined(__powerpc__)
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
{
uint32_t val, *ptr;
/* patch the branch destination */
ptr = (uint32_t *)jmp_addr;
val = *ptr;
val = (val & ~0x03fffffc) | ((addr - jmp_addr) & 0x03fffffc);
*ptr = val;
/* flush icache */
asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory");
asm volatile ("sync" : : : "memory");
asm volatile ("icbi 0,%0" : : "r"(ptr) : "memory");
asm volatile ("sync" : : : "memory");
asm volatile ("isync" : : : "memory");
}
#elif defined(__i386__)
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
{
/* patch the branch destination */
*(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
/* no need to flush icache explicitely */
}
#endif
static inline void tb_set_jmp_target(TranslationBlock *tb,
int n, unsigned long addr)
{
unsigned long offset;
offset = tb->tb_jmp_offset[n];
tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
offset = tb->tb_jmp_offset[n + 2];
if (offset != 0xffff)
tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
}
#else
/* set the jump target */
static inline void tb_set_jmp_target(TranslationBlock *tb,
int n, unsigned long addr)
{
tb->tb_next[n] = addr;
}
#endif
static inline void tb_add_jump(TranslationBlock *tb, int n,
TranslationBlock *tb_next)
{
/* NOTE: this test is only needed for thread safety */
if (!tb->jmp_next[n]) {
/* patch the native jump address */
tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr);
/* add in TB jmp circular list */
tb->jmp_next[n] = tb_next->jmp_first;
tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n));
}
}
TranslationBlock *tb_find_pc(unsigned long pc_ptr);
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif
#if defined(_WIN32)
#define ASM_DATA_SECTION ".section \".data\"\n"
#define ASM_PREVIOUS_SECTION ".section .text\n"
#elif defined(__APPLE__)
#define ASM_DATA_SECTION ".data\n"
#define ASM_PREVIOUS_SECTION ".text\n"
#define ASM_NAME(x) "_" #x
#else
#define ASM_DATA_SECTION ".section \".data\"\n"
#define ASM_PREVIOUS_SECTION ".previous\n"
#define ASM_NAME(x) stringify(x)
#endif
#if defined(__powerpc__)
/* we patch the jump instruction directly */
#define JUMP_TB(opname, tbparam, n, eip)\
do {\
asm volatile (ASM_DATA_SECTION\
ASM_NAME(__op_label) #n "." ASM_NAME(opname) ":\n"\
".long 1f\n"\
ASM_PREVIOUS_SECTION \
"b " ASM_NAME(__op_jmp) #n "\n"\
"1:\n");\
T0 = (long)(tbparam) + (n);\
EIP = eip;\
EXIT_TB();\
} while (0)
#define JUMP_TB2(opname, tbparam, n)\
do {\
asm volatile ("b " ASM_NAME(__op_jmp) #n "\n");\
} while (0)
#elif defined(__i386__) && defined(USE_DIRECT_JUMP)
/* we patch the jump instruction directly */
#define JUMP_TB(opname, tbparam, n, eip)\
do {\
asm volatile (".section .data\n"\
ASM_NAME(__op_label) #n "." ASM_NAME(opname) ":\n"\
".long 1f\n"\
ASM_PREVIOUS_SECTION \
"jmp " ASM_NAME(__op_jmp) #n "\n"\
"1:\n");\
T0 = (long)(tbparam) + (n);\
EIP = eip;\
EXIT_TB();\
} while (0)
#define JUMP_TB2(opname, tbparam, n)\
do {\
asm volatile ("jmp " ASM_NAME(__op_jmp) #n "\n");\
} while (0)
#else
/* jump to next block operations (more portable code, does not need
cache flushing, but slower because of indirect jump) */
#define JUMP_TB(opname, tbparam, n, eip)\
do {\
static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
static void __attribute__((unused)) *dummy ## n = &&dummy_label ## n;\
goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
label ## n:\
T0 = (long)(tbparam) + (n);\
EIP = eip;\
dummy_label ## n:\
EXIT_TB();\
} while (0)
/* second jump to same destination 'n' */
#define JUMP_TB2(opname, tbparam, n)\
do {\
goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n - 2]);\
} while (0)
#endif
extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
#ifdef __powerpc__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__ (
"0: lwarx %0,0,%1\n"
" xor. %0,%3,%0\n"
" bne 1f\n"
" stwcx. %2,0,%1\n"
" bne- 0b\n"
"1: "
: "=&r" (ret)
: "r" (p), "r" (1), "r" (0)
: "cr0", "memory");
return ret;
}
#endif
#ifdef __i386__
static inline int testandset (int *p)
{
char ret;
long int readval;
__asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
: "=q" (ret), "=m" (*p), "=a" (readval)
: "r" (1), "m" (*p), "a" (0)
: "memory");
return ret;
}
#endif
#ifdef __x86_64__
static inline int testandset (int *p)
{
char ret;
int readval;
__asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
: "=q" (ret), "=m" (*p), "=a" (readval)
: "r" (1), "m" (*p), "a" (0)
: "memory");
return ret;
}
#endif
#ifdef __s390__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
" jl 0b"
: "=&d" (ret)
: "r" (1), "a" (p), "0" (*p)
: "cc", "memory" );
return ret;
}
#endif
#ifdef __alpha__
static inline int testandset (int *p)
{
int ret;
unsigned long one;
__asm__ __volatile__ ("0: mov 1,%2\n"
" ldl_l %0,%1\n"
" stl_c %2,%1\n"
" beq %2,1f\n"
".subsection 2\n"
"1: br 0b\n"
".previous"
: "=r" (ret), "=m" (*p), "=r" (one)
: "m" (*p));
return ret;
}
#endif
#ifdef __sparc__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__("ldstub [%1], %0"
: "=r" (ret)
: "r" (p)
: "memory");
return (ret ? 1 : 0);
}
#endif
#ifdef __arm__
static inline int testandset (int *spinlock)
{
register unsigned int ret;
__asm__ __volatile__("swp %0, %1, [%2]"
: "=r"(ret)
: "0"(1), "r"(spinlock));
return ret;
}
#endif
#ifdef __mc68000
static inline int testandset (int *p)
{
char ret;
__asm__ __volatile__("tas %1; sne %0"
: "=r" (ret)
: "m" (p)
: "cc","memory");
return ret == 0;
}
#endif
typedef int spinlock_t;
#define SPIN_LOCK_UNLOCKED 0
#if defined(CONFIG_USER_ONLY)
static inline void spin_lock(spinlock_t *lock)
{
while (testandset(lock));
}
static inline void spin_unlock(spinlock_t *lock)
{
*lock = 0;
}
static inline int spin_trylock(spinlock_t *lock)
{
return !testandset(lock);
}
#else
static inline void spin_lock(spinlock_t *lock)
{
}
static inline void spin_unlock(spinlock_t *lock)
{
}
static inline int spin_trylock(spinlock_t *lock)
{
return 1;
}
#endif
extern spinlock_t tb_lock;
extern int tb_invalidated_flag;
#if (defined(TARGET_I386) || defined(TARGET_PPC)) && \
!defined(CONFIG_USER_ONLY)
void tlb_fill(unsigned long addr, int is_write, int is_user,
void *retaddr);
#define ACCESS_TYPE 3
#define MEMSUFFIX _code
#define env cpu_single_env
#define DATA_SIZE 1
#include "softmmu_header.h"
#define DATA_SIZE 2
#include "softmmu_header.h"
#define DATA_SIZE 4
#include "softmmu_header.h"
#undef ACCESS_TYPE
#undef MEMSUFFIX
#undef env
#endif
#if defined(CONFIG_USER_ONLY)
static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
{
return addr;
}
#else
/* NOTE: this function can trigger an exception */
/* NOTE2: the returned address is not exactly the physical address: it
is the offset relative to phys_ram_base */
/* XXX: i386 target specific */
static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
{
int is_user, index;
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
#if defined(TARGET_I386)
is_user = ((env->hflags & HF_CPL_MASK) == 3);
#elif defined (TARGET_PPC)
is_user = msr_pr;
#else
#error "Unimplemented !"
#endif
if (__builtin_expect(env->tlb_read[is_user][index].address !=
(addr & TARGET_PAGE_MASK), 0)) {
#if defined (TARGET_PPC)
env->access_type = ACCESS_CODE;
ldub_code((void *)addr);
env->access_type = ACCESS_INT;
#else
ldub_code((void *)addr);
#endif
}
return addr + env->tlb_read[is_user][index].addend - (unsigned long)phys_ram_base;
}
#endif

1925
exec.c

File diff suppressed because it is too large Load Diff

359
exec.h
View File

@@ -1,359 +0,0 @@
/*
* internal execution defines for qemu
*
* Copyright (c) 2003 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 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
*/
/* allow to see translation results - the slowdown should be negligible, so we leave it */
#define DEBUG_DISAS
/* is_jmp field values */
#define DISAS_NEXT 0 /* next instruction can be analyzed */
#define DISAS_JUMP 1 /* only pc was modified dynamically */
#define DISAS_UPDATE 2 /* cpu state was modified dynamically */
#define DISAS_TB_JUMP 3 /* only pc was modified statically */
struct TranslationBlock;
/* XXX: make safe guess about sizes */
#define MAX_OP_PER_INSTR 32
#define OPC_BUF_SIZE 512
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
extern uint16_t gen_opc_buf[OPC_BUF_SIZE];
extern uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
extern uint32_t gen_opc_pc[OPC_BUF_SIZE];
extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
#if defined(TARGET_I386)
#define GEN_FLAG_CODE32_SHIFT 0
#define GEN_FLAG_ADDSEG_SHIFT 1
#define GEN_FLAG_SS32_SHIFT 2
#define GEN_FLAG_VM_SHIFT 3
#define GEN_FLAG_ST_SHIFT 4
#define GEN_FLAG_TF_SHIFT 8 /* same position as eflags */
#define GEN_FLAG_CPL_SHIFT 9
#define GEN_FLAG_IOPL_SHIFT 12 /* same position as eflags */
#endif
extern FILE *logfile;
extern int loglevel;
int gen_intermediate_code(struct TranslationBlock *tb);
int gen_intermediate_code_pc(struct TranslationBlock *tb);
void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf);
int cpu_gen_code(struct TranslationBlock *tb,
int max_code_size, int *gen_code_size_ptr);
int cpu_restore_state(struct TranslationBlock *tb,
CPUState *env, unsigned long searched_pc);
void cpu_exec_init(void);
int page_unprotect(unsigned long address);
void page_unmap(void);
#define CODE_GEN_MAX_SIZE 65536
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
#define CODE_GEN_HASH_BITS 15
#define CODE_GEN_HASH_SIZE (1 << CODE_GEN_HASH_BITS)
/* maximum total translate dcode allocated */
#define CODE_GEN_BUFFER_SIZE (2048 * 1024)
//#define CODE_GEN_BUFFER_SIZE (128 * 1024)
#if defined(__powerpc__)
#define USE_DIRECT_JUMP
#endif
typedef struct TranslationBlock {
unsigned long pc; /* simulated PC corresponding to this block (EIP + CS base) */
unsigned long cs_base; /* CS base for this block */
unsigned int flags; /* flags defining in which context the code was generated */
uint16_t size; /* size of target code for this block (1 <=
size <= TARGET_PAGE_SIZE) */
uint8_t *tc_ptr; /* pointer to the translated code */
struct TranslationBlock *hash_next; /* next matching block */
struct TranslationBlock *page_next[2]; /* next blocks in even/odd page */
/* the following data are used to directly call another TB from
the code of this one. */
uint16_t tb_next_offset[2]; /* offset of original jump target */
#ifdef USE_DIRECT_JUMP
uint16_t tb_jmp_offset[2]; /* offset of jump instruction */
#else
uint32_t tb_next[2]; /* address of jump generated code */
#endif
/* list of TBs jumping to this one. This is a circular list using
the two least significant bits of the pointers to tell what is
the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 =
jmp_first */
struct TranslationBlock *jmp_next[2];
struct TranslationBlock *jmp_first;
} TranslationBlock;
static inline unsigned int tb_hash_func(unsigned long pc)
{
return pc & (CODE_GEN_HASH_SIZE - 1);
}
TranslationBlock *tb_alloc(unsigned long pc);
void tb_flush(void);
void tb_link(TranslationBlock *tb);
extern TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
extern uint8_t *code_gen_ptr;
/* find a translation block in the translation cache. If not found,
return NULL and the pointer to the last element of the list in pptb */
static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
unsigned long pc,
unsigned long cs_base,
unsigned int flags)
{
TranslationBlock **ptb, *tb;
unsigned int h;
h = tb_hash_func(pc);
ptb = &tb_hash[h];
for(;;) {
tb = *ptb;
if (!tb)
break;
if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
return tb;
ptb = &tb->hash_next;
}
*pptb = ptb;
return NULL;
}
#if defined(__powerpc__)
static inline void tb_set_jmp_target(TranslationBlock *tb,
int n, unsigned long addr)
{
uint32_t val, *ptr;
unsigned long offset;
offset = (unsigned long)(tb->tc_ptr + tb->tb_jmp_offset[n]);
/* patch the branch destination */
ptr = (uint32_t *)offset;
val = *ptr;
val = (val & ~0x03fffffc) | ((addr - offset) & 0x03fffffc);
*ptr = val;
/* flush icache */
asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory");
asm volatile ("sync" : : : "memory");
asm volatile ("icbi 0,%0" : : "r"(ptr) : "memory");
asm volatile ("sync" : : : "memory");
asm volatile ("isync" : : : "memory");
}
#else
/* set the jump target */
static inline void tb_set_jmp_target(TranslationBlock *tb,
int n, unsigned long addr)
{
tb->tb_next[n] = addr;
}
#endif
static inline void tb_add_jump(TranslationBlock *tb, int n,
TranslationBlock *tb_next)
{
/* NOTE: this test is only needed for thread safety */
if (!tb->jmp_next[n]) {
/* patch the native jump address */
tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr);
/* add in TB jmp circular list */
tb->jmp_next[n] = tb_next->jmp_first;
tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n));
}
}
TranslationBlock *tb_find_pc(unsigned long pc_ptr);
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif
#if defined(__powerpc__)
/* on PowerPC we patch the jump instruction directly */
#define JUMP_TB(tbparam, n, eip)\
do {\
static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
asm volatile ("b %0" : : "i" (&__op_jmp ## n));\
label ## n:\
T0 = (long)(tbparam) + (n);\
EIP = eip;\
} while (0)
#else
/* jump to next block operations (more portable code, does not need
cache flushing, but slower because of indirect jump) */
#define JUMP_TB(tbparam, n, eip)\
do {\
static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
static void __attribute__((unused)) *dummy ## n = &&dummy_label ## n;\
goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
label ## n:\
T0 = (long)(tbparam) + (n);\
EIP = eip;\
dummy_label ## n:\
EXIT_TB();\
} while (0)
#endif
#ifdef __powerpc__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__ (
"0: lwarx %0,0,%1 ;"
" xor. %0,%3,%0;"
" bne 1f;"
" stwcx. %2,0,%1;"
" bne- 0b;"
"1: "
: "=&r" (ret)
: "r" (p), "r" (1), "r" (0)
: "cr0", "memory");
return ret;
}
#endif
#ifdef __i386__
static inline int testandset (int *p)
{
char ret;
long int readval;
__asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
: "=q" (ret), "=m" (*p), "=a" (readval)
: "r" (1), "m" (*p), "a" (0)
: "memory");
return ret;
}
#endif
#ifdef __s390__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
" jl 0b"
: "=&d" (ret)
: "r" (1), "a" (p), "0" (*p)
: "cc", "memory" );
return ret;
}
#endif
#ifdef __alpha__
static inline int testandset (int *p)
{
int ret;
unsigned long one;
__asm__ __volatile__ ("0: mov 1,%2\n"
" ldl_l %0,%1\n"
" stl_c %2,%1\n"
" beq %2,1f\n"
".subsection 2\n"
"1: br 0b\n"
".previous"
: "=r" (ret), "=m" (*p), "=r" (one)
: "m" (*p));
return ret;
}
#endif
#ifdef __sparc__
static inline int testandset (int *p)
{
int ret;
__asm__ __volatile__("ldstub [%1], %0"
: "=r" (ret)
: "r" (p)
: "memory");
return (ret ? 1 : 0);
}
#endif
#ifdef __arm__
static inline int testandset (int *spinlock)
{
register unsigned int ret;
__asm__ __volatile__("swp %0, %1, [%2]"
: "=r"(ret)
: "0"(1), "r"(spinlock));
return ret;
}
#endif
typedef int spinlock_t;
#define SPIN_LOCK_UNLOCKED 0
#if 1
static inline void spin_lock(spinlock_t *lock)
{
while (testandset(lock));
}
static inline void spin_unlock(spinlock_t *lock)
{
*lock = 0;
}
static inline int spin_trylock(spinlock_t *lock)
{
return !testandset(lock);
}
#else
static inline void spin_lock(spinlock_t *lock)
{
}
static inline void spin_unlock(spinlock_t *lock)
{
}
static inline int spin_trylock(spinlock_t *lock)
{
return 1;
}
#endif
extern spinlock_t tb_lock;

677
gdbstub.c
View File

@@ -17,86 +17,39 @@
* 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "vl.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <signal.h>
#include "config.h"
#ifdef TARGET_I386
#include "cpu-i386.h"
#endif
#ifdef TARGET_ARM
#include "cpu-arm.h"
#endif
#include "thunk.h"
#include "exec.h"
//#define DEBUG_GDB
int gdbstub_fd = -1;
enum RSState {
RS_IDLE,
RS_GETLINE,
RS_CHKSUM1,
RS_CHKSUM2,
};
/* return 0 if OK */
static int gdbstub_open(int port)
{
struct sockaddr_in sockaddr;
socklen_t len;
int fd, val, ret;
static int gdbserver_fd;
fd = socket(PF_INET, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket");
return -1;
}
typedef struct GDBState {
enum RSState state;
int fd;
char line_buf[4096];
int line_buf_index;
int line_csum;
} GDBState;
/* allow fast reuse */
val = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(port);
sockaddr.sin_addr.s_addr = 0;
ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
if (ret < 0) {
perror("bind");
return -1;
}
ret = listen(fd, 0);
if (ret < 0) {
perror("listen");
return -1;
}
/* now wait for one connection */
for(;;) {
len = sizeof(sockaddr);
gdbstub_fd = accept(fd, (struct sockaddr *)&sockaddr, &len);
if (gdbstub_fd < 0 && errno != EINTR) {
perror("accept");
return -1;
} else if (gdbstub_fd >= 0) {
break;
}
}
/* set short latency */
val = 1;
setsockopt(gdbstub_fd, SOL_TCP, TCP_NODELAY, &val, sizeof(val));
return 0;
}
static int get_char(void)
static int get_char(GDBState *s)
{
uint8_t ch;
int ret;
for(;;) {
ret = read(gdbstub_fd, &ch, 1);
ret = read(s->fd, &ch, 1);
if (ret < 0) {
if (errno != EINTR && errno != EAGAIN)
return -1;
@@ -109,12 +62,12 @@ static int get_char(void)
return ch;
}
static void put_buffer(const uint8_t *buf, int len)
static void put_buffer(GDBState *s, const uint8_t *buf, int len)
{
int ret;
while (len > 0) {
ret = write(gdbstub_fd, buf, len);
ret = write(s->fd, buf, len);
if (ret < 0) {
if (errno != EINTR && errno != EAGAIN)
return;
@@ -168,59 +121,8 @@ static void hextomem(uint8_t *mem, const char *buf, int len)
}
}
/* return -1 if error or EOF */
static int get_packet(char *buf, int buf_size)
{
int ch, len, csum, csum1;
char reply[1];
for(;;) {
for(;;) {
ch = get_char();
if (ch < 0)
return -1;
if (ch == '$')
break;
}
len = 0;
csum = 0;
for(;;) {
ch = get_char();
if (ch < 0)
return -1;
if (ch == '#')
break;
if (len > buf_size - 1)
return -1;
buf[len++] = ch;
csum += ch;
}
buf[len] = '\0';
ch = get_char();
if (ch < 0)
return -1;
csum1 = fromhex(ch) << 4;
ch = get_char();
if (ch < 0)
return -1;
csum1 |= fromhex(ch);
if ((csum & 0xff) != csum1) {
reply[0] = '-';
put_buffer(reply, 1);
} else {
reply[0] = '+';
put_buffer(reply, 1);
break;
}
}
#ifdef DEBUG_GDB
printf("command='%s'\n", buf);
#endif
return len;
}
/* return -1 if error, 0 if OK */
static int put_packet(char *buf)
static int put_packet(GDBState *s, char *buf)
{
char buf1[3];
int len, csum, ch, i;
@@ -231,9 +133,9 @@ static int put_packet(char *buf)
for(;;) {
buf1[0] = '$';
put_buffer(buf1, 1);
put_buffer(s, buf1, 1);
len = strlen(buf);
put_buffer(buf, len);
put_buffer(s, buf, len);
csum = 0;
for(i = 0; i < len; i++) {
csum += buf[i];
@@ -242,9 +144,9 @@ static int put_packet(char *buf)
buf1[1] = tohex((csum >> 4) & 0xf);
buf1[2] = tohex((csum) & 0xf);
put_buffer(buf1, 3);
put_buffer(s, buf1, 3);
ch = get_char();
ch = get_char(s);
if (ch < 0)
return -1;
if (ch == '+')
@@ -253,97 +155,58 @@ static int put_packet(char *buf)
return 0;
}
static int memory_rw(uint8_t *buf, uint32_t addr, int len, int is_write)
{
int l, flags;
uint32_t page;
#if defined(TARGET_I386)
while (len > 0) {
page = addr & TARGET_PAGE_MASK;
l = (page + TARGET_PAGE_SIZE) - addr;
if (l > len)
l = len;
flags = page_get_flags(page);
if (!(flags & PAGE_VALID))
return -1;
if (is_write) {
if (!(flags & PAGE_WRITE))
return -1;
memcpy((uint8_t *)addr, buf, l);
} else {
if (!(flags & PAGE_READ))
return -1;
memcpy(buf, (uint8_t *)addr, l);
}
len -= l;
buf += l;
addr += l;
}
return 0;
static void to_le32(uint8_t *p, int v)
{
p[0] = v;
p[1] = v >> 8;
p[2] = v >> 16;
p[3] = v >> 24;
}
/* port = 0 means default port */
int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port)
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
CPUState *env;
const char *p;
int ret, ch, nb_regs, i;
char buf[4096];
uint8_t mem_buf[2000];
uint32_t *registers;
uint32_t addr, len;
printf("Waiting gdb connection on port %d\n", port);
if (gdbstub_open(port) < 0)
return -1;
printf("Connected\n");
for(;;) {
ret = get_packet(buf, sizeof(buf));
if (ret < 0)
break;
p = buf;
ch = *p++;
switch(ch) {
case '?':
snprintf(buf, sizeof(buf), "S%02x", SIGTRAP);
put_packet(buf);
break;
case 'c':
main_loop(opaque);
snprintf(buf, sizeof(buf), "S%02x", 0);
put_packet(buf);
break;
case 'g':
env = cpu_gdbstub_get_env(opaque);
registers = (void *)mem_buf;
#if defined(TARGET_I386)
for(i = 0; i < 8; i++) {
registers[i] = tswapl(env->regs[i]);
}
registers[8] = env->eip;
registers[9] = env->eflags;
registers[10] = env->segs[R_CS].selector;
registers[11] = env->segs[R_SS].selector;
registers[12] = env->segs[R_DS].selector;
registers[13] = env->segs[R_ES].selector;
registers[14] = env->segs[R_FS].selector;
registers[15] = env->segs[R_GS].selector;
nb_regs = 16;
#endif
memtohex(buf, (const uint8_t *)registers,
sizeof(registers[0]) * nb_regs);
put_packet(buf);
break;
case 'G':
env = cpu_gdbstub_get_env(opaque);
registers = (void *)mem_buf;
#if defined(TARGET_I386)
hextomem((uint8_t *)registers, p, 16 * 4);
for(i = 0; i < 8; i++) {
env->regs[i] = tswapl(registers[i]);
}
env->eip = registers[8];
env->eflags = registers[9];
int i, fpus;
for(i = 0; i < 8; i++) {
to_le32(mem_buf + i * 4, env->regs[i]);
}
to_le32(mem_buf + 8 * 4, env->eip);
to_le32(mem_buf + 9 * 4, env->eflags);
to_le32(mem_buf + 10 * 4, env->segs[R_CS].selector);
to_le32(mem_buf + 11 * 4, env->segs[R_SS].selector);
to_le32(mem_buf + 12 * 4, env->segs[R_DS].selector);
to_le32(mem_buf + 13 * 4, env->segs[R_ES].selector);
to_le32(mem_buf + 14 * 4, env->segs[R_FS].selector);
to_le32(mem_buf + 15 * 4, env->segs[R_GS].selector);
/* XXX: convert floats */
for(i = 0; i < 8; i++) {
memcpy(mem_buf + 16 * 4 + i * 10, &env->fpregs[i], 10);
}
to_le32(mem_buf + 36 * 4, env->fpuc);
fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
to_le32(mem_buf + 37 * 4, fpus);
to_le32(mem_buf + 38 * 4, 0); /* XXX: convert tags */
to_le32(mem_buf + 39 * 4, 0); /* fiseg */
to_le32(mem_buf + 40 * 4, 0); /* fioff */
to_le32(mem_buf + 41 * 4, 0); /* foseg */
to_le32(mem_buf + 42 * 4, 0); /* fooff */
to_le32(mem_buf + 43 * 4, 0); /* fop */
return 44 * 4;
}
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
uint32_t *registers = (uint32_t *)mem_buf;
int i;
for(i = 0; i < 8; i++) {
env->regs[i] = tswapl(registers[i]);
}
env->eip = registers[8];
env->eflags = registers[9];
#if defined(CONFIG_USER_ONLY)
#define LOAD_SEG(index, sreg)\
if (tswapl(registers[index]) != env->segs[sreg].selector)\
cpu_x86_load_seg(env, sreg, tswapl(registers[index]));
@@ -354,37 +217,379 @@ int cpu_gdbstub(void *opaque, void (*main_loop)(void *opaque), int port)
LOAD_SEG(14, R_FS);
LOAD_SEG(15, R_GS);
#endif
put_packet("OK");
break;
case 'm':
}
#elif defined (TARGET_PPC)
static void to_le32(uint32_t *buf, uint32_t v)
{
uint8_t *p = (uint8_t *)buf;
p[3] = v;
p[2] = v >> 8;
p[1] = v >> 16;
p[0] = v >> 24;
}
static uint32_t from_le32 (uint32_t *buf)
{
uint8_t *p = (uint8_t *)buf;
return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
}
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
uint32_t *registers = (uint32_t *)mem_buf, tmp;
int i;
/* fill in gprs */
for(i = 0; i < 32; i++) {
to_le32(&registers[i], env->gpr[i]);
}
/* fill in fprs */
for (i = 0; i < 32; i++) {
to_le32(&registers[(i * 2) + 32], *((uint32_t *)&env->fpr[i]));
to_le32(&registers[(i * 2) + 33], *((uint32_t *)&env->fpr[i] + 1));
}
/* nip, msr, ccr, lnk, ctr, xer, mq */
to_le32(&registers[96], (uint32_t)env->nip/* - 4*/);
to_le32(&registers[97], _load_msr(env));
tmp = 0;
for (i = 0; i < 8; i++)
tmp |= env->crf[i] << (32 - ((i + 1) * 4));
to_le32(&registers[98], tmp);
to_le32(&registers[99], env->lr);
to_le32(&registers[100], env->ctr);
to_le32(&registers[101], _load_xer(env));
to_le32(&registers[102], 0);
return 103 * 4;
}
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
uint32_t *registers = (uint32_t *)mem_buf;
int i;
/* fill in gprs */
for (i = 0; i < 32; i++) {
env->gpr[i] = from_le32(&registers[i]);
}
/* fill in fprs */
for (i = 0; i < 32; i++) {
*((uint32_t *)&env->fpr[i]) = from_le32(&registers[(i * 2) + 32]);
*((uint32_t *)&env->fpr[i] + 1) = from_le32(&registers[(i * 2) + 33]);
}
/* nip, msr, ccr, lnk, ctr, xer, mq */
env->nip = from_le32(&registers[96]);
_store_msr(env, from_le32(&registers[97]));
registers[98] = from_le32(&registers[98]);
for (i = 0; i < 8; i++)
env->crf[i] = (registers[98] >> (32 - ((i + 1) * 4))) & 0xF;
env->lr = from_le32(&registers[99]);
env->ctr = from_le32(&registers[100]);
_store_xer(env, from_le32(&registers[101]));
}
#else
static int cpu_gdb_read_registers(CPUState *env, uint8_t *mem_buf)
{
return 0;
}
static void cpu_gdb_write_registers(CPUState *env, uint8_t *mem_buf, int size)
{
}
#endif
/* port = 0 means default port */
static int gdb_handle_packet(GDBState *s, const char *line_buf)
{
CPUState *env = cpu_single_env;
const char *p;
int ch, reg_size, type;
char buf[4096];
uint8_t mem_buf[2000];
uint32_t *registers;
uint32_t addr, len;
#ifdef DEBUG_GDB
printf("command='%s'\n", line_buf);
#endif
p = line_buf;
ch = *p++;
switch(ch) {
case '?':
snprintf(buf, sizeof(buf), "S%02x", SIGTRAP);
put_packet(s, buf);
break;
case 'c':
if (*p != '\0') {
addr = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, NULL, 16);
if (memory_rw(mem_buf, addr, len, 0) != 0)
memset(mem_buf, 0, len);
memtohex(buf, mem_buf, len);
put_packet(buf);
break;
case 'M':
#if defined(TARGET_I386)
env->eip = addr;
#elif defined (TARGET_PPC)
env->nip = addr;
#endif
}
vm_start();
break;
case 's':
if (*p != '\0') {
addr = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
hextomem(mem_buf, p, len);
if (memory_rw(mem_buf, addr, len, 1) != 0)
put_packet("ENN");
else
put_packet("OK");
#if defined(TARGET_I386)
env->eip = addr;
#elif defined (TARGET_PPC)
env->nip = addr;
#endif
}
cpu_single_step(env, 1);
vm_start();
break;
case 'g':
reg_size = cpu_gdb_read_registers(env, mem_buf);
memtohex(buf, mem_buf, reg_size);
put_packet(s, buf);
break;
case 'G':
registers = (void *)mem_buf;
len = strlen(p) / 2;
hextomem((uint8_t *)registers, p, len);
cpu_gdb_write_registers(env, mem_buf, len);
put_packet(s, "OK");
break;
case 'm':
addr = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, NULL, 16);
if (cpu_memory_rw_debug(env, addr, mem_buf, len, 0) != 0)
memset(mem_buf, 0, len);
memtohex(buf, mem_buf, len);
put_packet(s, buf);
break;
case 'M':
addr = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
hextomem(mem_buf, p, len);
if (cpu_memory_rw_debug(env, addr, mem_buf, len, 1) != 0)
put_packet(s, "ENN");
else
put_packet(s, "OK");
break;
case 'Z':
type = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
addr = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, (char **)&p, 16);
if (type == 0 || type == 1) {
if (cpu_breakpoint_insert(env, addr) < 0)
goto breakpoint_error;
put_packet(s, "OK");
} else {
breakpoint_error:
put_packet(s, "ENN");
}
break;
case 'z':
type = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
addr = strtoul(p, (char **)&p, 16);
if (*p == ',')
p++;
len = strtoul(p, (char **)&p, 16);
if (type == 0 || type == 1) {
cpu_breakpoint_remove(env, addr);
put_packet(s, "OK");
} else {
goto breakpoint_error;
}
break;
default:
// unknown_command:
/* put empty packet */
buf[0] = '\0';
put_packet(s, buf);
break;
}
return RS_IDLE;
}
static void gdb_vm_stopped(void *opaque, int reason)
{
GDBState *s = opaque;
char buf[256];
int ret;
/* disable single step if it was enable */
cpu_single_step(cpu_single_env, 0);
if (reason == EXCP_DEBUG)
ret = SIGTRAP;
else
ret = 0;
snprintf(buf, sizeof(buf), "S%02x", ret);
put_packet(s, buf);
}
static void gdb_read_byte(GDBState *s, int ch)
{
int i, csum;
char reply[1];
if (vm_running) {
/* when the CPU is running, we cannot do anything except stop
it when receiving a char */
vm_stop(EXCP_INTERRUPT);
} else {
switch(s->state) {
case RS_IDLE:
if (ch == '$') {
s->line_buf_index = 0;
s->state = RS_GETLINE;
}
break;
default:
/* put empty packet */
buf[0] = '\0';
put_packet(buf);
case RS_GETLINE:
if (ch == '#') {
s->state = RS_CHKSUM1;
} else if (s->line_buf_index >= sizeof(s->line_buf) - 1) {
s->state = RS_IDLE;
} else {
s->line_buf[s->line_buf_index++] = ch;
}
break;
case RS_CHKSUM1:
s->line_buf[s->line_buf_index] = '\0';
s->line_csum = fromhex(ch) << 4;
s->state = RS_CHKSUM2;
break;
case RS_CHKSUM2:
s->line_csum |= fromhex(ch);
csum = 0;
for(i = 0; i < s->line_buf_index; i++) {
csum += s->line_buf[i];
}
if (s->line_csum != (csum & 0xff)) {
reply[0] = '-';
put_buffer(s, reply, 1);
s->state = RS_IDLE;
} else {
reply[0] = '+';
put_buffer(s, reply, 1);
s->state = gdb_handle_packet(s, s->line_buf);
}
break;
}
}
}
static int gdb_can_read(void *opaque)
{
return 256;
}
static void gdb_read(void *opaque, const uint8_t *buf, int size)
{
GDBState *s = opaque;
int i;
if (size == 0) {
/* end of connection */
qemu_del_vm_stop_handler(gdb_vm_stopped, s);
qemu_del_fd_read_handler(s->fd);
qemu_free(s);
vm_start();
} else {
for(i = 0; i < size; i++)
gdb_read_byte(s, buf[i]);
}
}
static void gdb_accept(void *opaque, const uint8_t *buf, int size)
{
GDBState *s;
struct sockaddr_in sockaddr;
socklen_t len;
int val, fd;
for(;;) {
len = sizeof(sockaddr);
fd = accept(gdbserver_fd, (struct sockaddr *)&sockaddr, &len);
if (fd < 0 && errno != EINTR) {
perror("accept");
return;
} else if (fd >= 0) {
break;
}
}
/* set short latency */
val = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
s = qemu_mallocz(sizeof(GDBState));
if (!s) {
close(fd);
return;
}
s->fd = fd;
fcntl(fd, F_SETFL, O_NONBLOCK);
/* stop the VM */
vm_stop(EXCP_INTERRUPT);
/* start handling I/O */
qemu_add_fd_read_handler(s->fd, gdb_can_read, gdb_read, s);
/* when the VM is stopped, the following callback is called */
qemu_add_vm_stop_handler(gdb_vm_stopped, s);
}
static int gdbserver_open(int port)
{
struct sockaddr_in sockaddr;
int fd, val, ret;
fd = socket(PF_INET, SOCK_STREAM, 0);
if (fd < 0) {
perror("socket");
return -1;
}
/* allow fast reuse */
val = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(port);
sockaddr.sin_addr.s_addr = 0;
ret = bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr));
if (ret < 0) {
perror("bind");
return -1;
}
ret = listen(fd, 0);
if (ret < 0) {
perror("listen");
return -1;
}
fcntl(fd, F_SETFL, O_NONBLOCK);
return fd;
}
int gdbserver_start(int port)
{
gdbserver_fd = gdbserver_open(port);
if (gdbserver_fd < 0)
return -1;
/* accept connections */
qemu_add_fd_read_handler(gdbserver_fd, NULL, gdb_accept, NULL);
return 0;
}

File diff suppressed because it is too large Load Diff

362
hw/adb.c Normal file
View File

@@ -0,0 +1,362 @@
/*
* QEMU ADB support
*
* Copyright (c) 2004 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"
/* ADB commands */
#define ADB_BUSRESET 0x00
#define ADB_FLUSH 0x01
#define ADB_WRITEREG 0x08
#define ADB_READREG 0x0c
/* ADB device commands */
#define ADB_CMD_SELF_TEST 0xff
#define ADB_CMD_CHANGE_ID 0xfe
#define ADB_CMD_CHANGE_ID_AND_ACT 0xfd
#define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00
/* ADB default device IDs (upper 4 bits of ADB command byte) */
#define ADB_DONGLE 1
#define ADB_KEYBOARD 2
#define ADB_MOUSE 3
#define ADB_TABLET 4
#define ADB_MODEM 5
#define ADB_MISC 7
int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
{
ADBDevice *d;
int devaddr, cmd, i;
cmd = buf[0] & 0xf;
devaddr = buf[0] >> 4;
if (buf[1] == ADB_BUSRESET) {
obuf[0] = 0x00;
obuf[1] = 0x00;
return 2;
}
if (cmd == ADB_FLUSH) {
obuf[0] = 0x00;
obuf[1] = 0x00;
return 2;
}
for(i = 0; i < s->nb_devices; i++) {
d = &s->devices[i];
if (d->devaddr == devaddr) {
return d->devreq(d, obuf, buf, len);
}
}
return 0;
}
int adb_poll(ADBBusState *s, uint8_t *obuf)
{
ADBDevice *d;
int olen, i;
olen = 0;
for(i = 0; i < s->nb_devices; i++) {
if (s->poll_index >= s->nb_devices)
s->poll_index = 0;
d = &s->devices[s->poll_index];
olen = d->devreq(d, obuf, NULL, 0);
s->poll_index++;
if (olen)
break;
}
return olen;
}
ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
ADBDeviceRequest *devreq,
void *opaque)
{
ADBDevice *d;
if (s->nb_devices >= MAX_ADB_DEVICES)
return NULL;
d = &s->devices[s->nb_devices++];
d->bus = s;
d->devaddr = devaddr;
d->devreq = devreq;
d->opaque = opaque;
return d;
}
/***************************************************************/
/* Keyboard ADB device */
typedef struct KBDState {
uint8_t data[128];
int rptr, wptr, count;
} KBDState;
static const uint8_t pc_to_adb_keycode[256] = {
0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9,
11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,125, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 75, 0, 0,124, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,115, 62,116, 0, 59, 0, 60, 0,119,
61,121,114,117, 0, 0, 0, 0, 0, 0, 0, 55,126, 0,127, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
static void adb_kbd_put_keycode(void *opaque, int keycode)
{
ADBDevice *d = opaque;
KBDState *s = d->opaque;
if (s->count < sizeof(s->data)) {
s->data[s->wptr] = keycode;
if (++s->wptr == sizeof(s->data))
s->wptr = 0;
s->count++;
}
}
static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
{
static int ext_keycode;
KBDState *s = d->opaque;
int adb_keycode, keycode;
int olen;
olen = 0;
for(;;) {
if (s->count == 0)
break;
keycode = s->data[s->rptr];
if (++s->rptr == sizeof(s->data))
s->rptr = 0;
s->count--;
if (keycode == 0xe0) {
ext_keycode = 1;
} else {
if (ext_keycode)
adb_keycode = pc_to_adb_keycode[keycode | 0x80];
else
adb_keycode = pc_to_adb_keycode[keycode & 0x7f];
obuf[0] = (d->devaddr << 4) | 0x0c;
obuf[1] = adb_keycode | (keycode & 0x80);
obuf[2] = 0xff;
olen = 3;
ext_keycode = 0;
break;
}
}
return olen;
}
static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
const uint8_t *buf, int len)
{
int cmd, reg, olen;
if (!buf) {
return adb_kbd_poll(d, obuf);
}
cmd = buf[0] & 0xc;
reg = buf[0] & 0x3;
olen = 0;
switch(cmd) {
case ADB_WRITEREG:
switch(reg) {
case 2:
/* LED status */
break;
case 3:
switch(buf[2]) {
case ADB_CMD_SELF_TEST:
break;
case ADB_CMD_CHANGE_ID:
case ADB_CMD_CHANGE_ID_AND_ACT:
case ADB_CMD_CHANGE_ID_AND_ENABLE:
d->devaddr = buf[1] & 0xf;
break;
default:
/* XXX: check this */
d->devaddr = buf[1] & 0xf;
d->handler = buf[2];
break;
}
}
break;
case ADB_READREG:
switch(reg) {
case 1:
break;
case 2:
obuf[0] = 0x00; /* XXX: check this */
obuf[1] = 0x07; /* led status */
olen = 2;
break;
case 3:
obuf[0] = d->handler;
obuf[1] = d->devaddr;
olen = 2;
break;
}
break;
}
return olen;
}
void adb_kbd_init(ADBBusState *bus)
{
ADBDevice *d;
KBDState *s;
s = qemu_mallocz(sizeof(KBDState));
d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request, s);
d->handler = 1;
qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
}
/***************************************************************/
/* Mouse ADB device */
typedef struct MouseState {
int buttons_state, last_buttons_state;
int dx, dy, dz;
} MouseState;
static void adb_mouse_event(void *opaque,
int dx1, int dy1, int dz1, int buttons_state)
{
ADBDevice *d = opaque;
MouseState *s = d->opaque;
s->dx += dx1;
s->dy += dy1;
s->dz += dz1;
s->buttons_state = buttons_state;
}
static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
{
MouseState *s = d->opaque;
int dx, dy;
if (s->last_buttons_state == s->buttons_state &&
s->dx == 0 && s->dy == 0)
return 0;
dx = s->dx;
if (dx < -63)
dx = -63;
else if (dx > 63)
dx = 63;
dy = s->dy;
if (dy < -63)
dy = -63;
else if (dy > 63)
dy = 63;
s->dx -= dx;
s->dy -= dy;
s->last_buttons_state = s->buttons_state;
dx &= 0x7f;
dy &= 0x7f;
if (s->buttons_state & MOUSE_EVENT_LBUTTON)
dy |= 0x80;
if (s->buttons_state & MOUSE_EVENT_RBUTTON)
dx |= 0x80;
obuf[0] = (d->devaddr << 4) | 0x0c;
obuf[1] = dy;
obuf[2] = dx;
return 3;
}
static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
const uint8_t *buf, int len)
{
int cmd, reg, olen;
if (!buf) {
return adb_mouse_poll(d, obuf);
}
cmd = buf[0] & 0xc;
reg = buf[0] & 0x3;
olen = 0;
switch(cmd) {
case ADB_WRITEREG:
switch(reg) {
case 2:
break;
case 3:
switch(buf[2]) {
case ADB_CMD_SELF_TEST:
break;
case ADB_CMD_CHANGE_ID:
case ADB_CMD_CHANGE_ID_AND_ACT:
case ADB_CMD_CHANGE_ID_AND_ENABLE:
d->devaddr = buf[1] & 0xf;
break;
default:
/* XXX: check this */
d->devaddr = buf[1] & 0xf;
break;
}
}
break;
case ADB_READREG:
switch(reg) {
case 1:
break;
case 3:
obuf[0] = d->handler;
obuf[1] = d->devaddr;
olen = 2;
break;
}
break;
}
return olen;
}
void adb_mouse_init(ADBBusState *bus)
{
ADBDevice *d;
MouseState *s;
s = qemu_mallocz(sizeof(MouseState));
d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request, s);
d->handler = 2;
qemu_add_mouse_event_handler(adb_mouse_event, d);
}

3045
hw/cirrus_vga.c Normal file

File diff suppressed because it is too large Load Diff

78
hw/cirrus_vga_rop.h Normal file
View File

@@ -0,0 +1,78 @@
/*
* QEMU Cirrus CLGD 54xx VGA Emulator.
*
* Copyright (c) 2004 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.
*/
static void
glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
uint8_t *dst,const uint8_t *src,
int dstpitch,int srcpitch,
int bltwidth,int bltheight)
{
int x,y;
dstpitch -= bltwidth;
srcpitch -= bltwidth;
for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x++) {
ROP_OP(*dst, *src);
dst++;
src++;
}
dst += dstpitch;
src += srcpitch;
}
}
static void
glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
uint8_t *dst,const uint8_t *src,
int dstpitch,int srcpitch,
int bltwidth,int bltheight)
{
int x,y;
dstpitch += bltwidth;
srcpitch += bltwidth;
for (y = 0; y < bltheight; y++) {
for (x = 0; x < bltwidth; x++) {
ROP_OP(*dst, *src);
dst--;
src--;
}
dst += dstpitch;
src += srcpitch;
}
}
#define DEPTH 8
#include "cirrus_vga_rop2.h"
#define DEPTH 16
#include "cirrus_vga_rop2.h"
#define DEPTH 24
#include "cirrus_vga_rop2.h"
#define DEPTH 32
#include "cirrus_vga_rop2.h"
#undef ROP_NAME
#undef ROP_OP

260
hw/cirrus_vga_rop2.h Normal file
View File

@@ -0,0 +1,260 @@
/*
* QEMU Cirrus CLGD 54xx VGA Emulator.
*
* Copyright (c) 2004 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.
*/
#if DEPTH == 8
#define PUTPIXEL() ROP_OP(d[0], col)
#elif DEPTH == 16
#define PUTPIXEL() ROP_OP(((uint16_t *)d)[0], col);
#elif DEPTH == 24
#define PUTPIXEL() ROP_OP(d[0], col); \
ROP_OP(d[1], (col >> 8)); \
ROP_OP(d[2], (col >> 16))
#elif DEPTH == 32
#define PUTPIXEL() ROP_OP(((uint32_t *)d)[0], col)
#else
#error unsupported DEPTH
#endif
static void
glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint8_t *d;
int x, y, pattern_y, pattern_pitch, pattern_x;
unsigned int col;
const uint8_t *src1;
#if DEPTH == 8
pattern_pitch = 8;
#elif DEPTH == 16
pattern_pitch = 16;
#else
pattern_pitch = 32;
#endif
pattern_y = s->cirrus_blt_srcaddr & 7;
pattern_x = 0;
for(y = 0; y < bltheight; y++) {
d = dst;
src1 = src + pattern_y * pattern_pitch;
for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
#if DEPTH == 8
col = src1[pattern_x];
pattern_x = (pattern_x + 1) & 7;
#elif DEPTH == 16
col = ((uint16_t *)(src1 + pattern_x))[0];
pattern_x = (pattern_x + 2) & 15;
#elif DEPTH == 24
{
const uint8_t *src2 = src1 + pattern_x * 3;
col = src2[0] | (src2[1] << 8) | (src2[2] << 16);
pattern_x = (pattern_x + 1) & 7;
}
#else
col = ((uint32_t *)(src1 + pattern_x))[0];
pattern_x = (pattern_x + 4) & 31;
#endif
PUTPIXEL();
d += (DEPTH / 8);
}
pattern_y = (pattern_y + 1) & 7;
dst += dstpitch;
}
}
/* NOTE: srcpitch is ignored */
static void
glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint8_t *d;
int x, y;
unsigned bits, bits_xor;
unsigned int col;
unsigned bitmask;
unsigned index;
int srcskipleft = 0;
if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
bits_xor = 0xff;
col = s->cirrus_blt_bgcol;
} else {
bits_xor = 0x00;
col = s->cirrus_blt_fgcol;
}
for(y = 0; y < bltheight; y++) {
bitmask = 0x80 >> srcskipleft;
bits = *src++ ^ bits_xor;
d = dst;
for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
bits = *src++ ^ bits_xor;
}
index = (bits & bitmask);
if (index) {
PUTPIXEL();
}
d += (DEPTH / 8);
bitmask >>= 1;
}
dst += dstpitch;
}
}
static void
glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint32_t colors[2];
uint8_t *d;
int x, y;
unsigned bits;
unsigned int col;
unsigned bitmask;
int srcskipleft = 0;
colors[0] = s->cirrus_blt_bgcol;
colors[1] = s->cirrus_blt_fgcol;
for(y = 0; y < bltheight; y++) {
bitmask = 0x80 >> srcskipleft;
bits = *src++;
d = dst;
for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
if ((bitmask & 0xff) == 0) {
bitmask = 0x80;
bits = *src++;
}
col = colors[!!(bits & bitmask)];
PUTPIXEL();
d += (DEPTH / 8);
bitmask >>= 1;
}
dst += dstpitch;
}
}
static void
glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint8_t *d;
int x, y, bitpos, pattern_y;
unsigned int bits, bits_xor;
unsigned int col;
if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
bits_xor = 0xff;
col = s->cirrus_blt_bgcol;
} else {
bits_xor = 0x00;
col = s->cirrus_blt_fgcol;
}
pattern_y = s->cirrus_blt_srcaddr & 7;
for(y = 0; y < bltheight; y++) {
bits = src[pattern_y] ^ bits_xor;
bitpos = 7;
d = dst;
for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
if ((bits >> bitpos) & 1) {
PUTPIXEL();
}
d += (DEPTH / 8);
bitpos = (bitpos - 1) & 7;
}
pattern_y = (pattern_y + 1) & 7;
dst += dstpitch;
}
}
static void
glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
(CirrusVGAState * s, uint8_t * dst,
const uint8_t * src,
int dstpitch, int srcpitch,
int bltwidth, int bltheight)
{
uint32_t colors[2];
uint8_t *d;
int x, y, bitpos, pattern_y;
unsigned int bits;
unsigned int col;
colors[0] = s->cirrus_blt_bgcol;
colors[1] = s->cirrus_blt_fgcol;
pattern_y = s->cirrus_blt_srcaddr & 7;
for(y = 0; y < bltheight; y++) {
bits = src[pattern_y];
bitpos = 7;
d = dst;
for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
col = colors[(bits >> bitpos) & 1];
PUTPIXEL();
d += (DEPTH / 8);
bitpos = (bitpos - 1) & 7;
}
pattern_y = (pattern_y + 1) & 7;
dst += dstpitch;
}
}
static void
glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
(CirrusVGAState *s,
uint8_t *dst, int dst_pitch,
int width, int height)
{
uint8_t *d, *d1;
uint32_t col;
int x, y;
col = s->cirrus_blt_fgcol;
d1 = dst;
for(y = 0; y < height; y++) {
d = d1;
for(x = 0; x < width; x += (DEPTH / 8)) {
PUTPIXEL();
d += (DEPTH / 8);
}
d1 += dst_pitch;
}
}
#undef DEPTH
#undef PUTPIXEL

613
hw/cuda.c Normal file
View File

@@ -0,0 +1,613 @@
/*
* QEMU CUDA support
*
* Copyright (c) 2004 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"
//#define DEBUG_CUDA
//#define DEBUG_CUDA_PACKET
/* Bits in B data register: all active low */
#define TREQ 0x08 /* Transfer request (input) */
#define TACK 0x10 /* Transfer acknowledge (output) */
#define TIP 0x20 /* Transfer in progress (output) */
/* Bits in ACR */
#define SR_CTRL 0x1c /* Shift register control bits */
#define SR_EXT 0x0c /* Shift on external clock */
#define SR_OUT 0x10 /* Shift out if 1 */
/* Bits in IFR and IER */
#define IER_SET 0x80 /* set bits in IER */
#define IER_CLR 0 /* clear bits in IER */
#define SR_INT 0x04 /* Shift register full/empty */
#define T1_INT 0x40 /* Timer 1 interrupt */
/* Bits in ACR */
#define T1MODE 0xc0 /* Timer 1 mode */
#define T1MODE_CONT 0x40 /* continuous interrupts */
/* commands (1st byte) */
#define ADB_PACKET 0
#define CUDA_PACKET 1
#define ERROR_PACKET 2
#define TIMER_PACKET 3
#define POWER_PACKET 4
#define MACIIC_PACKET 5
#define PMU_PACKET 6
/* CUDA commands (2nd byte) */
#define CUDA_WARM_START 0x0
#define CUDA_AUTOPOLL 0x1
#define CUDA_GET_6805_ADDR 0x2
#define CUDA_GET_TIME 0x3
#define CUDA_GET_PRAM 0x7
#define CUDA_SET_6805_ADDR 0x8
#define CUDA_SET_TIME 0x9
#define CUDA_POWERDOWN 0xa
#define CUDA_POWERUP_TIME 0xb
#define CUDA_SET_PRAM 0xc
#define CUDA_MS_RESET 0xd
#define CUDA_SEND_DFAC 0xe
#define CUDA_BATTERY_SWAP_SENSE 0x10
#define CUDA_RESET_SYSTEM 0x11
#define CUDA_SET_IPL 0x12
#define CUDA_FILE_SERVER_FLAG 0x13
#define CUDA_SET_AUTO_RATE 0x14
#define CUDA_GET_AUTO_RATE 0x16
#define CUDA_SET_DEVICE_LIST 0x19
#define CUDA_GET_DEVICE_LIST 0x1a
#define CUDA_SET_ONE_SECOND_MODE 0x1b
#define CUDA_SET_POWER_MESSAGES 0x21
#define CUDA_GET_SET_IIC 0x22
#define CUDA_WAKEUP 0x23
#define CUDA_TIMER_TICKLE 0x24
#define CUDA_COMBINED_FORMAT_IIC 0x25
#define CUDA_TIMER_FREQ (4700000 / 6)
#define CUDA_ADB_POLL_FREQ 50
typedef struct CUDATimer {
unsigned int latch;
uint16_t counter_value; /* counter value at load time */
int64_t load_time;
int64_t next_irq_time;
QEMUTimer *timer;
} CUDATimer;
typedef struct CUDAState {
/* cuda registers */
uint8_t b; /* B-side data */
uint8_t a; /* A-side data */
uint8_t dirb; /* B-side direction (1=output) */
uint8_t dira; /* A-side direction (1=output) */
uint8_t sr; /* Shift register */
uint8_t acr; /* Auxiliary control register */
uint8_t pcr; /* Peripheral control register */
uint8_t ifr; /* Interrupt flag register */
uint8_t ier; /* Interrupt enable register */
uint8_t anh; /* A-side data, no handshake */
CUDATimer timers[2];
uint8_t last_b; /* last value of B register */
uint8_t last_acr; /* last value of B register */
int data_in_size;
int data_in_index;
int data_out_index;
int irq;
openpic_t *openpic;
uint8_t autopoll;
uint8_t data_in[128];
uint8_t data_out[16];
QEMUTimer *adb_poll_timer;
} CUDAState;
static CUDAState cuda_state;
ADBBusState adb_bus;
static void cuda_update(CUDAState *s);
static void cuda_receive_packet_from_host(CUDAState *s,
const uint8_t *data, int len);
static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
int64_t current_time);
static void cuda_update_irq(CUDAState *s)
{
if (s->ifr & s->ier & (SR_INT | T1_INT)) {
openpic_set_irq(s->openpic, s->irq, 1);
} else {
openpic_set_irq(s->openpic, s->irq, 0);
}
}
static unsigned int get_counter(CUDATimer *s)
{
int64_t d;
unsigned int counter;
d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
CUDA_TIMER_FREQ, ticks_per_sec);
if (d <= s->counter_value) {
counter = d;
} else {
counter = s->latch - 1 - ((d - s->counter_value) % s->latch);
}
return counter;
}
static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
{
#ifdef DEBUG_CUDA
printf("cuda: T%d.counter=%d\n",
1 + (ti->timer == NULL), val);
#endif
ti->load_time = qemu_get_clock(vm_clock);
ti->counter_value = val;
cuda_timer_update(s, ti, ti->load_time);
}
static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
{
int64_t d, next_time, base;
/* current counter value */
d = muldiv64(current_time - s->load_time,
CUDA_TIMER_FREQ, ticks_per_sec);
if (d <= s->counter_value) {
next_time = s->counter_value + 1;
} else {
base = ((d - s->counter_value) / s->latch);
base = (base * s->latch) + s->counter_value;
next_time = base + s->latch;
}
#ifdef DEBUG_CUDA
printf("latch=%d counter=%lld delta_next=%lld\n",
s->latch, d, next_time - d);
#endif
next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) +
s->load_time;
if (next_time <= current_time)
next_time = current_time + 1;
return next_time;
}
static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
int64_t current_time)
{
if (!ti->timer)
return;
if ((s->acr & T1MODE) != T1MODE_CONT) {
qemu_del_timer(ti->timer);
} else {
ti->next_irq_time = get_next_irq_time(ti, current_time);
qemu_mod_timer(ti->timer, ti->next_irq_time);
}
}
static void cuda_timer1(void *opaque)
{
CUDAState *s = opaque;
CUDATimer *ti = &s->timers[0];
cuda_timer_update(s, ti, ti->next_irq_time);
s->ifr |= T1_INT;
cuda_update_irq(s);
}
static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
{
CUDAState *s = opaque;
uint32_t val;
addr = (addr >> 9) & 0xf;
switch(addr) {
case 0:
val = s->b;
break;
case 1:
val = s->a;
break;
case 2:
val = s->dirb;
break;
case 3:
val = s->dira;
break;
case 4:
val = get_counter(&s->timers[0]) & 0xff;
s->ifr &= ~T1_INT;
cuda_update_irq(s);
break;
case 5:
val = get_counter(&s->timers[0]) >> 8;
s->ifr &= ~T1_INT;
cuda_update_irq(s);
break;
case 6:
val = s->timers[0].latch & 0xff;
break;
case 7:
val = (s->timers[0].latch >> 8) & 0xff;
break;
case 8:
val = get_counter(&s->timers[1]) & 0xff;
break;
case 9:
val = get_counter(&s->timers[1]) >> 8;
break;
case 10:
val = s->sr;
s->ifr &= ~SR_INT;
cuda_update_irq(s);
break;
case 11:
val = s->acr;
break;
case 12:
val = s->pcr;
break;
case 13:
val = s->ifr;
break;
case 14:
val = s->ier;
break;
default:
case 15:
val = s->anh;
break;
}
#ifdef DEBUG_CUDA
if (addr != 13 || val != 0)
printf("cuda: read: reg=0x%x val=%02x\n", addr, val);
#endif
return val;
}
static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
{
CUDAState *s = opaque;
addr = (addr >> 9) & 0xf;
#ifdef DEBUG_CUDA
printf("cuda: write: reg=0x%x val=%02x\n", addr, val);
#endif
switch(addr) {
case 0:
s->b = val;
cuda_update(s);
break;
case 1:
s->a = val;
break;
case 2:
s->dirb = val;
break;
case 3:
s->dira = val;
break;
case 4:
val = val | (get_counter(&s->timers[0]) & 0xff00);
set_counter(s, &s->timers[0], val);
break;
case 5:
val = (val << 8) | (get_counter(&s->timers[0]) & 0xff);
set_counter(s, &s->timers[0], val);
break;
case 6:
s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
break;
case 7:
s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
break;
case 8:
val = val | (get_counter(&s->timers[1]) & 0xff00);
set_counter(s, &s->timers[1], val);
break;
case 9:
val = (val << 8) | (get_counter(&s->timers[1]) & 0xff);
set_counter(s, &s->timers[1], val);
break;
case 10:
s->sr = val;
break;
case 11:
s->acr = val;
cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
cuda_update(s);
break;
case 12:
s->pcr = val;
break;
case 13:
/* reset bits */
s->ifr &= ~val;
cuda_update_irq(s);
break;
case 14:
if (val & IER_SET) {
/* set bits */
s->ier |= val & 0x7f;
} else {
/* reset bits */
s->ier &= ~val;
}
cuda_update_irq(s);
break;
default:
case 15:
s->anh = val;
break;
}
}
/* NOTE: TIP and TREQ are negated */
static void cuda_update(CUDAState *s)
{
int packet_received, len;
packet_received = 0;
if (!(s->b & TIP)) {
/* transfer requested from host */
if (s->acr & SR_OUT) {
/* data output */
if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
if (s->data_out_index < sizeof(s->data_out)) {
#ifdef DEBUG_CUDA
printf("cuda: send: %02x\n", s->sr);
#endif
s->data_out[s->data_out_index++] = s->sr;
s->ifr |= SR_INT;
cuda_update_irq(s);
}
}
} else {
if (s->data_in_index < s->data_in_size) {
/* data input */
if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
s->sr = s->data_in[s->data_in_index++];
#ifdef DEBUG_CUDA
printf("cuda: recv: %02x\n", s->sr);
#endif
/* indicate end of transfer */
if (s->data_in_index >= s->data_in_size) {
s->b = (s->b | TREQ);
}
s->ifr |= SR_INT;
cuda_update_irq(s);
}
}
}
} else {
/* no transfer requested: handle sync case */
if ((s->last_b & TIP) && (s->b & TACK) != (s->last_b & TACK)) {
/* update TREQ state each time TACK change state */
if (s->b & TACK)
s->b = (s->b | TREQ);
else
s->b = (s->b & ~TREQ);
s->ifr |= SR_INT;
cuda_update_irq(s);
} else {
if (!(s->last_b & TIP)) {
/* handle end of host to cuda transfert */
packet_received = (s->data_out_index > 0);
/* always an IRQ at the end of transfert */
s->ifr |= SR_INT;
cuda_update_irq(s);
}
/* signal if there is data to read */
if (s->data_in_index < s->data_in_size) {
s->b = (s->b & ~TREQ);
}
}
}
s->last_acr = s->acr;
s->last_b = s->b;
/* NOTE: cuda_receive_packet_from_host() can call cuda_update()
recursively */
if (packet_received) {
len = s->data_out_index;
s->data_out_index = 0;
cuda_receive_packet_from_host(s, s->data_out, len);
}
}
static void cuda_send_packet_to_host(CUDAState *s,
const uint8_t *data, int len)
{
#ifdef DEBUG_CUDA_PACKET
{
int i;
printf("cuda_send_packet_to_host:\n");
for(i = 0; i < len; i++)
printf(" %02x", data[i]);
printf("\n");
}
#endif
memcpy(s->data_in, data, len);
s->data_in_size = len;
s->data_in_index = 0;
cuda_update(s);
s->ifr |= SR_INT;
cuda_update_irq(s);
}
static void cuda_adb_poll(void *opaque)
{
CUDAState *s = opaque;
uint8_t obuf[ADB_MAX_OUT_LEN + 2];
int olen;
olen = adb_poll(&adb_bus, obuf + 2);
if (olen > 0) {
obuf[0] = ADB_PACKET;
obuf[1] = 0x40; /* polled data */
cuda_send_packet_to_host(s, obuf, olen + 2);
}
qemu_mod_timer(s->adb_poll_timer,
qemu_get_clock(vm_clock) +
(ticks_per_sec / CUDA_ADB_POLL_FREQ));
}
static void cuda_receive_packet(CUDAState *s,
const uint8_t *data, int len)
{
uint8_t obuf[16];
int ti, autopoll;
switch(data[0]) {
case CUDA_AUTOPOLL:
autopoll = (data[1] != 0);
if (autopoll != s->autopoll) {
s->autopoll = autopoll;
if (autopoll) {
qemu_mod_timer(s->adb_poll_timer,
qemu_get_clock(vm_clock) +
(ticks_per_sec / CUDA_ADB_POLL_FREQ));
} else {
qemu_del_timer(s->adb_poll_timer);
}
}
obuf[0] = CUDA_PACKET;
obuf[1] = data[1];
cuda_send_packet_to_host(s, obuf, 2);
break;
case CUDA_GET_TIME:
/* XXX: add time support ? */
ti = time(NULL);
obuf[0] = CUDA_PACKET;
obuf[1] = 0;
obuf[2] = 0;
obuf[3] = ti >> 24;
obuf[4] = ti >> 16;
obuf[5] = ti >> 8;
obuf[6] = ti;
cuda_send_packet_to_host(s, obuf, 7);
break;
case CUDA_SET_TIME:
case CUDA_FILE_SERVER_FLAG:
case CUDA_SET_DEVICE_LIST:
case CUDA_SET_AUTO_RATE:
case CUDA_SET_POWER_MESSAGES:
obuf[0] = CUDA_PACKET;
obuf[1] = 0;
cuda_send_packet_to_host(s, obuf, 2);
break;
default:
break;
}
}
static void cuda_receive_packet_from_host(CUDAState *s,
const uint8_t *data, int len)
{
#ifdef DEBUG_CUDA_PACKET
{
int i;
printf("cuda_receive_packet_to_host:\n");
for(i = 0; i < len; i++)
printf(" %02x", data[i]);
printf("\n");
}
#endif
switch(data[0]) {
case ADB_PACKET:
{
uint8_t obuf[ADB_MAX_OUT_LEN + 2];
int olen;
olen = adb_request(&adb_bus, obuf + 2, data + 1, len - 1);
if (olen != 0) {
obuf[0] = ADB_PACKET;
obuf[1] = 0x00;
} else {
/* empty reply */
obuf[0] = ADB_PACKET;
obuf[1] = 0x02;
}
cuda_send_packet_to_host(s, obuf, olen + 2);
}
break;
case CUDA_PACKET:
cuda_receive_packet(s, data + 1, len - 1);
break;
}
}
static void cuda_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
}
static void cuda_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
}
static uint32_t cuda_readw (void *opaque, target_phys_addr_t addr)
{
return 0;
}
static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr)
{
return 0;
}
static CPUWriteMemoryFunc *cuda_write[] = {
&cuda_writeb,
&cuda_writew,
&cuda_writel,
};
static CPUReadMemoryFunc *cuda_read[] = {
&cuda_readb,
&cuda_readw,
&cuda_readl,
};
int cuda_init(openpic_t *openpic, int irq)
{
CUDAState *s = &cuda_state;
int cuda_mem_index;
s->openpic = openpic;
s->irq = irq;
s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);
s->timers[0].latch = 0x10000;
set_counter(s, &s->timers[0], 0xffff);
s->timers[1].latch = 0x10000;
s->ier = T1_INT | SR_INT;
set_counter(s, &s->timers[1], 0xffff);
s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
return cuda_mem_index;
}

430
hw/dma.c Normal file
View File

@@ -0,0 +1,430 @@
/*
* QEMU DMA emulation
*
* Copyright (c) 2003 Vassili Karpov (malc)
*
* 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"
//#define DEBUG_DMA
#define log(...) fprintf (stderr, "dma: " __VA_ARGS__)
#ifdef DEBUG_DMA
#define lwarn(...) fprintf (stderr, "dma: " __VA_ARGS__)
#define linfo(...) fprintf (stderr, "dma: " __VA_ARGS__)
#define ldebug(...) fprintf (stderr, "dma: " __VA_ARGS__)
#else
#define lwarn(...)
#define linfo(...)
#define ldebug(...)
#endif
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
struct dma_regs {
int now[2];
uint16_t base[2];
uint8_t mode;
uint8_t page;
uint8_t pageh;
uint8_t dack;
uint8_t eop;
DMA_transfer_handler transfer_handler;
void *opaque;
};
#define ADDR 0
#define COUNT 1
static struct dma_cont {
uint8_t status;
uint8_t command;
uint8_t mask;
uint8_t flip_flop;
int dshift;
struct dma_regs regs[4];
} dma_controllers[2];
enum {
CMD_MEMORY_TO_MEMORY = 0x01,
CMD_FIXED_ADDRESS = 0x02,
CMD_BLOCK_CONTROLLER = 0x04,
CMD_COMPRESSED_TIME = 0x08,
CMD_CYCLIC_PRIORITY = 0x10,
CMD_EXTENDED_WRITE = 0x20,
CMD_LOW_DREQ = 0x40,
CMD_LOW_DACK = 0x80,
CMD_NOT_SUPPORTED = CMD_MEMORY_TO_MEMORY | CMD_FIXED_ADDRESS
| CMD_COMPRESSED_TIME | CMD_CYCLIC_PRIORITY | CMD_EXTENDED_WRITE
| CMD_LOW_DREQ | CMD_LOW_DACK
};
static int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
static void write_page (void *opaque, uint32_t nport, uint32_t data)
{
struct dma_cont *d = opaque;
int ichan;
ichan = channels[nport & 7];
if (-1 == ichan) {
log ("invalid channel %#x %#x\n", nport, data);
return;
}
d->regs[ichan].page = data;
}
static void write_pageh (void *opaque, uint32_t nport, uint32_t data)
{
struct dma_cont *d = opaque;
int ichan;
ichan = channels[nport & 7];
if (-1 == ichan) {
log ("invalid channel %#x %#x\n", nport, data);
return;
}
d->regs[ichan].pageh = data;
}
static uint32_t read_page (void *opaque, uint32_t nport)
{
struct dma_cont *d = opaque;
int ichan;
ichan = channels[nport & 7];
if (-1 == ichan) {
log ("invalid channel read %#x\n", nport);
return 0;
}
return d->regs[ichan].page;
}
static uint32_t read_pageh (void *opaque, uint32_t nport)
{
struct dma_cont *d = opaque;
int ichan;
ichan = channels[nport & 7];
if (-1 == ichan) {
log ("invalid channel read %#x\n", nport);
return 0;
}
return d->regs[ichan].pageh;
}
static inline void init_chan (struct dma_cont *d, int ichan)
{
struct dma_regs *r;
r = d->regs + ichan;
r->now[ADDR] = r->base[0] << d->dshift;
r->now[COUNT] = 0;
}
static inline int getff (struct dma_cont *d)
{
int ff;
ff = d->flip_flop;
d->flip_flop = !ff;
return ff;
}
static uint32_t read_chan (void *opaque, uint32_t nport)
{
struct dma_cont *d = opaque;
int ichan, nreg, iport, ff, val;
struct dma_regs *r;
iport = (nport >> d->dshift) & 0x0f;
ichan = iport >> 1;
nreg = iport & 1;
r = d->regs + ichan;
ff = getff (d);
if (nreg)
val = (r->base[COUNT] << d->dshift) - r->now[COUNT];
else
val = r->now[ADDR] + r->now[COUNT];
return (val >> (d->dshift + (ff << 3))) & 0xff;
}
static void write_chan (void *opaque, uint32_t nport, uint32_t data)
{
struct dma_cont *d = opaque;
int iport, ichan, nreg;
struct dma_regs *r;
iport = (nport >> d->dshift) & 0x0f;
ichan = iport >> 1;
nreg = iport & 1;
r = d->regs + ichan;
if (getff (d)) {
r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00);
init_chan (d, ichan);
} else {
r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff);
}
}
static void write_cont (void *opaque, uint32_t nport, uint32_t data)
{
struct dma_cont *d = opaque;
int iport, ichan;
iport = (nport >> d->dshift) & 0x0f;
switch (iport) {
case 8: /* command */
if ((data != 0) && (data & CMD_NOT_SUPPORTED)) {
log ("command %#x not supported\n", data);
return;
}
d->command = data;
break;
case 9:
ichan = data & 3;
if (data & 4) {
d->status |= 1 << (ichan + 4);
}
else {
d->status &= ~(1 << (ichan + 4));
}
d->status &= ~(1 << ichan);
break;
case 0xa: /* single mask */
if (data & 4)
d->mask |= 1 << (data & 3);
else
d->mask &= ~(1 << (data & 3));
break;
case 0xb: /* mode */
{
ichan = data & 3;
#ifdef DEBUG_DMA
int op;
int ai;
int dir;
int opmode;
op = (data >> 2) & 3;
ai = (data >> 4) & 1;
dir = (data >> 5) & 1;
opmode = (data >> 6) & 3;
linfo ("ichan %d, op %d, ai %d, dir %d, opmode %d\n",
ichan, op, ai, dir, opmode);
#endif
d->regs[ichan].mode = data;
break;
}
case 0xc: /* clear flip flop */
d->flip_flop = 0;
break;
case 0xd: /* reset */
d->flip_flop = 0;
d->mask = ~0;
d->status = 0;
d->command = 0;
break;
case 0xe: /* clear mask for all channels */
d->mask = 0;
break;
case 0xf: /* write mask for all channels */
d->mask = data;
break;
default:
log ("dma: unknown iport %#x\n", iport);
break;
}
#ifdef DEBUG_DMA
if (0xc != iport) {
linfo ("nport %#06x, ichan % 2d, val %#06x\n",
nport, ichan, data);
}
#endif
}
static uint32_t read_cont (void *opaque, uint32_t nport)
{
struct dma_cont *d = opaque;
int iport, val;
iport = (nport >> d->dshift) & 0x0f;
switch (iport) {
case 0x08: /* status */
val = d->status;
d->status &= 0xf0;
break;
case 0x0f: /* mask */
val = d->mask;
break;
default:
val = 0;
break;
}
return val;
}
int DMA_get_channel_mode (int nchan)
{
return dma_controllers[nchan > 3].regs[nchan & 3].mode;
}
void DMA_hold_DREQ (int nchan)
{
int ncont, ichan;
ncont = nchan > 3;
ichan = nchan & 3;
linfo ("held cont=%d chan=%d\n", ncont, ichan);
dma_controllers[ncont].status |= 1 << (ichan + 4);
}
void DMA_release_DREQ (int nchan)
{
int ncont, ichan;
ncont = nchan > 3;
ichan = nchan & 3;
linfo ("released cont=%d chan=%d\n", ncont, ichan);
dma_controllers[ncont].status &= ~(1 << (ichan + 4));
}
static void channel_run (int ncont, int ichan)
{
struct dma_regs *r;
int n;
target_ulong addr;
/* int ai, dir; */
r = dma_controllers[ncont].regs + ichan;
/* ai = r->mode & 16; */
/* dir = r->mode & 32 ? -1 : 1; */
/* NOTE: pageh is only used by PPC PREP */
addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
n = r->transfer_handler (r->opaque, addr,
(r->base[COUNT] << ncont) + (1 << ncont));
r->now[COUNT] = n;
ldebug ("dma_pos %d size %d\n",
n, (r->base[1] << ncont) + (1 << ncont));
}
void DMA_run (void)
{
struct dma_cont *d;
int icont, ichan;
d = dma_controllers;
for (icont = 0; icont < 2; icont++, d++) {
for (ichan = 0; ichan < 4; ichan++) {
int mask;
mask = 1 << ichan;
if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4))))
channel_run (icont, ichan);
}
}
}
void DMA_register_channel (int nchan,
DMA_transfer_handler transfer_handler,
void *opaque)
{
struct dma_regs *r;
int ichan, ncont;
ncont = nchan > 3;
ichan = nchan & 3;
r = dma_controllers[ncont].regs + ichan;
r->transfer_handler = transfer_handler;
r->opaque = opaque;
}
/* request the emulator to transfer a new DMA memory block ASAP */
void DMA_schedule(int nchan)
{
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
}
static void dma_reset(void *opaque)
{
struct dma_cont *d = opaque;
write_cont (d, (0x0d << d->dshift), 0);
}
/* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */
static void dma_init2(struct dma_cont *d, int base, int dshift,
int page_base, int pageh_base)
{
const static int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
int i;
d->dshift = dshift;
for (i = 0; i < 8; i++) {
register_ioport_write (base + (i << dshift), 1, 1, write_chan, d);
register_ioport_read (base + (i << dshift), 1, 1, read_chan, d);
}
for (i = 0; i < LENOFA (page_port_list); i++) {
register_ioport_write (page_base + page_port_list[i], 1, 1,
write_page, d);
register_ioport_read (page_base + page_port_list[i], 1, 1,
read_page, d);
if (pageh_base >= 0) {
register_ioport_write (pageh_base + page_port_list[i], 1, 1,
write_pageh, d);
register_ioport_read (pageh_base + page_port_list[i], 1, 1,
read_pageh, d);
}
}
for (i = 0; i < 8; i++) {
register_ioport_write (base + ((i + 8) << dshift), 1, 1,
write_cont, d);
register_ioport_read (base + ((i + 8) << dshift), 1, 1,
read_cont, d);
}
qemu_register_reset(dma_reset, d);
dma_reset(d);
}
void DMA_init (int high_page_enable)
{
dma_init2(&dma_controllers[0], 0x00, 0, 0x80,
high_page_enable ? 0x480 : -1);
dma_init2(&dma_controllers[1], 0xc0, 1, 0x88,
high_page_enable ? 0x488 : -1);
}

1695
hw/fdc.c Normal file

File diff suppressed because it is too large Load Diff

470
hw/i8254.c Normal file
View File

@@ -0,0 +1,470 @@
/*
* QEMU 8253/8254 interval timer emulation
*
* Copyright (c) 2003-2004 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"
//#define DEBUG_PIT
#define RW_STATE_LSB 1
#define RW_STATE_MSB 2
#define RW_STATE_WORD0 3
#define RW_STATE_WORD1 4
typedef struct PITChannelState {
int count; /* can be 65536 */
uint16_t latched_count;
uint8_t count_latched;
uint8_t status_latched;
uint8_t status;
uint8_t read_state;
uint8_t write_state;
uint8_t write_latch;
uint8_t rw_mode;
uint8_t mode;
uint8_t bcd; /* not supported */
uint8_t gate; /* timer start */
int64_t count_load_time;
/* irq handling */
int64_t next_transition_time;
QEMUTimer *irq_timer;
int irq;
} PITChannelState;
struct PITState {
PITChannelState channels[3];
};
static PITState pit_state;
static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
static int pit_get_count(PITChannelState *s)
{
uint64_t d;
int counter;
d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, PIT_FREQ, ticks_per_sec);
switch(s->mode) {
case 0:
case 1:
case 4:
case 5:
counter = (s->count - d) & 0xffff;
break;
case 3:
/* XXX: may be incorrect for odd counts */
counter = s->count - ((2 * d) % s->count);
break;
default:
counter = s->count - (d % s->count);
break;
}
return counter;
}
/* get pit output bit */
static int pit_get_out1(PITChannelState *s, int64_t current_time)
{
uint64_t d;
int out;
d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
switch(s->mode) {
default:
case 0:
out = (d >= s->count);
break;
case 1:
out = (d < s->count);
break;
case 2:
if ((d % s->count) == 0 && d != 0)
out = 1;
else
out = 0;
break;
case 3:
out = (d % s->count) < ((s->count + 1) >> 1);
break;
case 4:
case 5:
out = (d == s->count);
break;
}
return out;
}
int pit_get_out(PITState *pit, int channel, int64_t current_time)
{
PITChannelState *s = &pit->channels[channel];
return pit_get_out1(s, current_time);
}
/* return -1 if no transition will occur. */
static int64_t pit_get_next_transition_time(PITChannelState *s,
int64_t current_time)
{
uint64_t d, next_time, base;
int period2;
d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
switch(s->mode) {
default:
case 0:
case 1:
if (d < s->count)
next_time = s->count;
else
return -1;
break;
case 2:
base = (d / s->count) * s->count;
if ((d - base) == 0 && d != 0)
next_time = base + s->count;
else
next_time = base + s->count + 1;
break;
case 3:
base = (d / s->count) * s->count;
period2 = ((s->count + 1) >> 1);
if ((d - base) < period2)
next_time = base + period2;
else
next_time = base + s->count;
break;
case 4:
case 5:
if (d < s->count)
next_time = s->count;
else if (d == s->count)
next_time = s->count + 1;
else
return -1;
break;
}
/* convert to timer units */
next_time = s->count_load_time + muldiv64(next_time, ticks_per_sec, PIT_FREQ);
/* fix potential rounding problems */
/* XXX: better solution: use a clock at PIT_FREQ Hz */
if (next_time <= current_time)
next_time = current_time + 1;
return next_time;
}
/* val must be 0 or 1 */
void pit_set_gate(PITState *pit, int channel, int val)
{
PITChannelState *s = &pit->channels[channel];
switch(s->mode) {
default:
case 0:
case 4:
/* XXX: just disable/enable counting */
break;
case 1:
case 5:
if (s->gate < val) {
/* restart counting on rising edge */
s->count_load_time = qemu_get_clock(vm_clock);
pit_irq_timer_update(s, s->count_load_time);
}
break;
case 2:
case 3:
if (s->gate < val) {
/* restart counting on rising edge */
s->count_load_time = qemu_get_clock(vm_clock);
pit_irq_timer_update(s, s->count_load_time);
}
/* XXX: disable/enable counting */
break;
}
s->gate = val;
}
int pit_get_gate(PITState *pit, int channel)
{
PITChannelState *s = &pit->channels[channel];
return s->gate;
}
static inline void pit_load_count(PITChannelState *s, int val)
{
if (val == 0)
val = 0x10000;
s->count_load_time = qemu_get_clock(vm_clock);
s->count = val;
pit_irq_timer_update(s, s->count_load_time);
}
/* if already latched, do not latch again */
static void pit_latch_count(PITChannelState *s)
{
if (!s->count_latched) {
s->latched_count = pit_get_count(s);
s->count_latched = s->rw_mode;
}
}
static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
PITState *pit = opaque;
int channel, access;
PITChannelState *s;
addr &= 3;
if (addr == 3) {
channel = val >> 6;
if (channel == 3) {
/* read back command */
for(channel = 0; channel < 3; channel++) {
s = &pit->channels[channel];
if (val & (2 << channel)) {
if (!(val & 0x20)) {
pit_latch_count(s);
}
if (!(val & 0x10) && !s->status_latched) {
/* status latch */
/* XXX: add BCD and null count */
s->status = (pit_get_out1(s, qemu_get_clock(vm_clock)) << 7) |
(s->rw_mode << 4) |
(s->mode << 1) |
s->bcd;
s->status_latched = 1;
}
}
}
} else {
s = &pit->channels[channel];
access = (val >> 4) & 3;
if (access == 0) {
pit_latch_count(s);
} else {
s->rw_mode = access;
s->read_state = access;
s->write_state = access;
s->mode = (val >> 1) & 7;
s->bcd = val & 1;
/* XXX: update irq timer ? */
}
}
} else {
s = &pit->channels[addr];
switch(s->write_state) {
default:
case RW_STATE_LSB:
pit_load_count(s, val);
break;
case RW_STATE_MSB:
pit_load_count(s, val << 8);
break;
case RW_STATE_WORD0:
s->write_latch = val;
s->write_state = RW_STATE_WORD1;
break;
case RW_STATE_WORD1:
pit_load_count(s, s->write_latch | (val << 8));
s->write_state = RW_STATE_WORD0;
break;
}
}
}
static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
{
PITState *pit = opaque;
int ret, count;
PITChannelState *s;
addr &= 3;
s = &pit->channels[addr];
if (s->status_latched) {
s->status_latched = 0;
ret = s->status;
} else if (s->count_latched) {
switch(s->count_latched) {
default:
case RW_STATE_LSB:
ret = s->latched_count & 0xff;
s->count_latched = 0;
break;
case RW_STATE_MSB:
ret = s->latched_count >> 8;
s->count_latched = 0;
break;
case RW_STATE_WORD0:
ret = s->latched_count & 0xff;
s->count_latched = RW_STATE_MSB;
break;
}
} else {
switch(s->read_state) {
default:
case RW_STATE_LSB:
count = pit_get_count(s);
ret = count & 0xff;
break;
case RW_STATE_MSB:
count = pit_get_count(s);
ret = (count >> 8) & 0xff;
break;
case RW_STATE_WORD0:
count = pit_get_count(s);
ret = count & 0xff;
s->read_state = RW_STATE_WORD1;
break;
case RW_STATE_WORD1:
count = pit_get_count(s);
ret = (count >> 8) & 0xff;
s->read_state = RW_STATE_WORD0;
break;
}
}
return ret;
}
static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
{
int64_t expire_time;
int irq_level;
if (!s->irq_timer)
return;
expire_time = pit_get_next_transition_time(s, current_time);
irq_level = pit_get_out1(s, current_time);
pic_set_irq(s->irq, irq_level);
#ifdef DEBUG_PIT
printf("irq_level=%d next_delay=%f\n",
irq_level,
(double)(expire_time - current_time) / ticks_per_sec);
#endif
s->next_transition_time = expire_time;
if (expire_time != -1)
qemu_mod_timer(s->irq_timer, expire_time);
else
qemu_del_timer(s->irq_timer);
}
static void pit_irq_timer(void *opaque)
{
PITChannelState *s = opaque;
pit_irq_timer_update(s, s->next_transition_time);
}
static void pit_save(QEMUFile *f, void *opaque)
{
PITState *pit = opaque;
PITChannelState *s;
int i;
for(i = 0; i < 3; i++) {
s = &pit->channels[i];
qemu_put_be32s(f, &s->count);
qemu_put_be16s(f, &s->latched_count);
qemu_put_8s(f, &s->count_latched);
qemu_put_8s(f, &s->status_latched);
qemu_put_8s(f, &s->status);
qemu_put_8s(f, &s->read_state);
qemu_put_8s(f, &s->write_state);
qemu_put_8s(f, &s->write_latch);
qemu_put_8s(f, &s->rw_mode);
qemu_put_8s(f, &s->mode);
qemu_put_8s(f, &s->bcd);
qemu_put_8s(f, &s->gate);
qemu_put_be64s(f, &s->count_load_time);
if (s->irq_timer) {
qemu_put_be64s(f, &s->next_transition_time);
qemu_put_timer(f, s->irq_timer);
}
}
}
static int pit_load(QEMUFile *f, void *opaque, int version_id)
{
PITState *pit = opaque;
PITChannelState *s;
int i;
if (version_id != 1)
return -EINVAL;
for(i = 0; i < 3; i++) {
s = &pit->channels[i];
qemu_get_be32s(f, &s->count);
qemu_get_be16s(f, &s->latched_count);
qemu_get_8s(f, &s->count_latched);
qemu_get_8s(f, &s->status_latched);
qemu_get_8s(f, &s->status);
qemu_get_8s(f, &s->read_state);
qemu_get_8s(f, &s->write_state);
qemu_get_8s(f, &s->write_latch);
qemu_get_8s(f, &s->rw_mode);
qemu_get_8s(f, &s->mode);
qemu_get_8s(f, &s->bcd);
qemu_get_8s(f, &s->gate);
qemu_get_be64s(f, &s->count_load_time);
if (s->irq_timer) {
qemu_get_be64s(f, &s->next_transition_time);
qemu_get_timer(f, s->irq_timer);
}
}
return 0;
}
static void pit_reset(void *opaque)
{
PITState *pit = opaque;
PITChannelState *s;
int i;
for(i = 0;i < 3; i++) {
s = &pit->channels[i];
s->mode = 3;
s->gate = (i != 2);
pit_load_count(s, 0);
}
}
PITState *pit_init(int base, int irq)
{
PITState *pit = &pit_state;
PITChannelState *s;
s = &pit->channels[0];
/* the timer 0 is connected to an IRQ */
s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
s->irq = irq;
register_savevm("i8254", base, 1, pit_save, pit_load, pit);
qemu_register_reset(pit_reset, pit);
register_ioport_write(base, 4, 1, pit_ioport_write, pit);
register_ioport_read(base, 3, 1, pit_ioport_read, pit);
pit_reset(pit);
return pit;
}

510
hw/i8259.c Normal file
View File

@@ -0,0 +1,510 @@
/*
* QEMU 8259 interrupt controller emulation
*
* Copyright (c) 2003-2004 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 PIC */
//#define DEBUG_PIC
//#define DEBUG_IRQ_LATENCY
//#define DEBUG_IRQ_COUNT
typedef struct PicState {
uint8_t last_irr; /* edge detection */
uint8_t irr; /* interrupt request register */
uint8_t imr; /* interrupt mask register */
uint8_t isr; /* interrupt service register */
uint8_t priority_add; /* highest irq priority */
uint8_t irq_base;
uint8_t read_reg_select;
uint8_t poll;
uint8_t special_mask;
uint8_t init_state;
uint8_t auto_eoi;
uint8_t rotate_on_auto_eoi;
uint8_t special_fully_nested_mode;
uint8_t init4; /* true if 4 byte init */
uint8_t elcr; /* PIIX edge/trigger selection*/
uint8_t elcr_mask;
} PicState;
/* 0 is master pic, 1 is slave pic */
static PicState pics[2];
#if defined(DEBUG_PIC) || defined (DEBUG_IRQ_COUNT)
static int irq_level[16];
#endif
#ifdef DEBUG_IRQ_COUNT
static uint64_t irq_count[16];
#endif
/* set irq level. If an edge is detected, then the IRR is set to 1 */
static inline void pic_set_irq1(PicState *s, int irq, int level)
{
int mask;
mask = 1 << irq;
if (s->elcr & mask) {
/* level triggered */
if (level) {
s->irr |= mask;
s->last_irr |= mask;
} else {
s->irr &= ~mask;
s->last_irr &= ~mask;
}
} else {
/* edge triggered */
if (level) {
if ((s->last_irr & mask) == 0)
s->irr |= mask;
s->last_irr |= mask;
} else {
s->last_irr &= ~mask;
}
}
}
/* return the highest priority found in mask (highest = smallest
number). Return 8 if no irq */
static inline int get_priority(PicState *s, int mask)
{
int priority;
if (mask == 0)
return 8;
priority = 0;
while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
priority++;
return priority;
}
/* return the pic wanted interrupt. return -1 if none */
static int pic_get_irq(PicState *s)
{
int mask, cur_priority, priority;
mask = s->irr & ~s->imr;
priority = get_priority(s, mask);
if (priority == 8)
return -1;
/* compute current priority. If special fully nested mode on the
master, the IRQ coming from the slave is not taken into account
for the priority computation. */
mask = s->isr;
if (s->special_fully_nested_mode && s == &pics[0])
mask &= ~(1 << 2);
cur_priority = get_priority(s, mask);
if (priority < cur_priority) {
/* higher priority found: an irq should be generated */
return (priority + s->priority_add) & 7;
} else {
return -1;
}
}
/* raise irq to CPU if necessary. must be called every time the active
irq may change */
static void pic_update_irq(void)
{
int irq2, irq;
/* first look at slave pic */
irq2 = pic_get_irq(&pics[1]);
if (irq2 >= 0) {
/* if irq request by slave pic, signal master PIC */
pic_set_irq1(&pics[0], 2, 1);
pic_set_irq1(&pics[0], 2, 0);
}
/* look at requested irq */
irq = pic_get_irq(&pics[0]);
if (irq >= 0) {
#if defined(DEBUG_PIC)
{
int i;
for(i = 0; i < 2; i++) {
printf("pic%d: imr=%x irr=%x padd=%d\n",
i, pics[i].imr, pics[i].irr, pics[i].priority_add);
}
}
printf("pic: cpu_interrupt\n");
#endif
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
}
}
#ifdef DEBUG_IRQ_LATENCY
int64_t irq_time[16];
#endif
void pic_set_irq(int irq, int level)
{
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
if (level != irq_level[irq]) {
#if defined(DEBUG_PIC)
printf("pic_set_irq: irq=%d level=%d\n", irq, level);
#endif
irq_level[irq] = level;
#ifdef DEBUG_IRQ_COUNT
if (level == 1)
irq_count[irq]++;
#endif
}
#endif
#ifdef DEBUG_IRQ_LATENCY
if (level) {
irq_time[irq] = qemu_get_clock(vm_clock);
}
#endif
pic_set_irq1(&pics[irq >> 3], irq & 7, level);
pic_update_irq();
}
/* acknowledge interrupt 'irq' */
static inline void pic_intack(PicState *s, int irq)
{
if (s->auto_eoi) {
if (s->rotate_on_auto_eoi)
s->priority_add = (irq + 1) & 7;
} else {
s->isr |= (1 << irq);
}
s->irr &= ~(1 << irq);
}
int cpu_get_pic_interrupt(CPUState *env)
{
int irq, irq2, intno;
/* read the irq from the PIC */
irq = pic_get_irq(&pics[0]);
if (irq >= 0) {
pic_intack(&pics[0], irq);
if (irq == 2) {
irq2 = pic_get_irq(&pics[1]);
if (irq2 >= 0) {
pic_intack(&pics[1], irq2);
} else {
/* spurious IRQ on slave controller */
irq2 = 7;
}
intno = pics[1].irq_base + irq2;
irq = irq2 + 8;
} else {
intno = pics[0].irq_base + irq;
}
} else {
/* spurious IRQ on host controller */
irq = 7;
intno = pics[0].irq_base + irq;
}
pic_update_irq();
#ifdef DEBUG_IRQ_LATENCY
printf("IRQ%d latency=%0.3fus\n",
irq,
(double)(qemu_get_clock(vm_clock) - irq_time[irq]) * 1000000.0 / ticks_per_sec);
#endif
#if defined(DEBUG_PIC)
printf("pic_interrupt: irq=%d\n", irq);
#endif
return intno;
}
static void pic_reset(void *opaque)
{
PicState *s = opaque;
int tmp;
tmp = s->elcr_mask;
memset(s, 0, sizeof(PicState));
s->elcr_mask = tmp;
}
static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
PicState *s = opaque;
int priority, cmd, irq;
#ifdef DEBUG_PIC
printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val);
#endif
addr &= 1;
if (addr == 0) {
if (val & 0x10) {
/* init */
pic_reset(s);
/* deassert a pending interrupt */
cpu_reset_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
s->init_state = 1;
s->init4 = val & 1;
if (val & 0x02)
hw_error("single mode not supported");
if (val & 0x08)
hw_error("level sensitive irq not supported");
} else if (val & 0x08) {
if (val & 0x04)
s->poll = 1;
if (val & 0x02)
s->read_reg_select = val & 1;
if (val & 0x40)
s->special_mask = (val >> 5) & 1;
} else {
cmd = val >> 5;
switch(cmd) {
case 0:
case 4:
s->rotate_on_auto_eoi = cmd >> 2;
break;
case 1: /* end of interrupt */
case 5:
priority = get_priority(s, s->isr);
if (priority != 8) {
irq = (priority + s->priority_add) & 7;
s->isr &= ~(1 << irq);
if (cmd == 5)
s->priority_add = (irq + 1) & 7;
pic_update_irq();
}
break;
case 3:
irq = val & 7;
s->isr &= ~(1 << irq);
pic_update_irq();
break;
case 6:
s->priority_add = (val + 1) & 7;
pic_update_irq();
break;
case 7:
irq = val & 7;
s->isr &= ~(1 << irq);
s->priority_add = (irq + 1) & 7;
pic_update_irq();
break;
default:
/* no operation */
break;
}
}
} else {
switch(s->init_state) {
case 0:
/* normal mode */
s->imr = val;
pic_update_irq();
break;
case 1:
s->irq_base = val & 0xf8;
s->init_state = 2;
break;
case 2:
if (s->init4) {
s->init_state = 3;
} else {
s->init_state = 0;
}
break;
case 3:
s->special_fully_nested_mode = (val >> 4) & 1;
s->auto_eoi = (val >> 1) & 1;
s->init_state = 0;
break;
}
}
}
static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
{
int ret;
ret = pic_get_irq(s);
if (ret >= 0) {
if (addr1 >> 7) {
pics[0].isr &= ~(1 << 2);
pics[0].irr &= ~(1 << 2);
}
s->irr &= ~(1 << ret);
s->isr &= ~(1 << ret);
if (addr1 >> 7 || ret != 2)
pic_update_irq();
} else {
ret = 0x07;
pic_update_irq();
}
return ret;
}
static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
{
PicState *s = opaque;
unsigned int addr;
int ret;
addr = addr1;
addr &= 1;
if (s->poll) {
ret = pic_poll_read(s, addr1);
s->poll = 0;
} else {
if (addr == 0) {
if (s->read_reg_select)
ret = s->isr;
else
ret = s->irr;
} else {
ret = s->imr;
}
}
#ifdef DEBUG_PIC
printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret);
#endif
return ret;
}
/* memory mapped interrupt status */
uint32_t pic_intack_read(CPUState *env)
{
int ret;
ret = pic_poll_read(&pics[0], 0x00);
if (ret == 2)
ret = pic_poll_read(&pics[1], 0x80) + 8;
/* Prepare for ISR read */
pics[0].read_reg_select = 1;
return ret;
}
static void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
PicState *s = opaque;
s->elcr = val & s->elcr_mask;
}
static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1)
{
PicState *s = opaque;
return s->elcr;
}
static void pic_save(QEMUFile *f, void *opaque)
{
PicState *s = opaque;
qemu_put_8s(f, &s->last_irr);
qemu_put_8s(f, &s->irr);
qemu_put_8s(f, &s->imr);
qemu_put_8s(f, &s->isr);
qemu_put_8s(f, &s->priority_add);
qemu_put_8s(f, &s->irq_base);
qemu_put_8s(f, &s->read_reg_select);
qemu_put_8s(f, &s->poll);
qemu_put_8s(f, &s->special_mask);
qemu_put_8s(f, &s->init_state);
qemu_put_8s(f, &s->auto_eoi);
qemu_put_8s(f, &s->rotate_on_auto_eoi);
qemu_put_8s(f, &s->special_fully_nested_mode);
qemu_put_8s(f, &s->init4);
qemu_put_8s(f, &s->elcr);
}
static int pic_load(QEMUFile *f, void *opaque, int version_id)
{
PicState *s = opaque;
if (version_id != 1)
return -EINVAL;
qemu_get_8s(f, &s->last_irr);
qemu_get_8s(f, &s->irr);
qemu_get_8s(f, &s->imr);
qemu_get_8s(f, &s->isr);
qemu_get_8s(f, &s->priority_add);
qemu_get_8s(f, &s->irq_base);
qemu_get_8s(f, &s->read_reg_select);
qemu_get_8s(f, &s->poll);
qemu_get_8s(f, &s->special_mask);
qemu_get_8s(f, &s->init_state);
qemu_get_8s(f, &s->auto_eoi);
qemu_get_8s(f, &s->rotate_on_auto_eoi);
qemu_get_8s(f, &s->special_fully_nested_mode);
qemu_get_8s(f, &s->init4);
qemu_get_8s(f, &s->elcr);
return 0;
}
/* XXX: add generic master/slave system */
static void pic_init1(int io_addr, int elcr_addr, PicState *s)
{
register_ioport_write(io_addr, 2, 1, pic_ioport_write, s);
register_ioport_read(io_addr, 2, 1, pic_ioport_read, s);
if (elcr_addr >= 0) {
register_ioport_write(elcr_addr, 1, 1, elcr_ioport_write, s);
register_ioport_read(elcr_addr, 1, 1, elcr_ioport_read, s);
}
register_savevm("i8259", io_addr, 1, pic_save, pic_load, s);
qemu_register_reset(pic_reset, s);
}
void pic_info(void)
{
int i;
PicState *s;
for(i=0;i<2;i++) {
s = &pics[i];
term_printf("pic%d: irr=%02x imr=%02x isr=%02x hprio=%d irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
i, s->irr, s->imr, s->isr, s->priority_add,
s->irq_base, s->read_reg_select, s->elcr,
s->special_fully_nested_mode);
}
}
void irq_info(void)
{
#ifndef DEBUG_IRQ_COUNT
term_printf("irq statistic code not compiled.\n");
#else
int i;
int64_t count;
term_printf("IRQ statistics:\n");
for (i = 0; i < 16; i++) {
count = irq_count[i];
if (count > 0)
term_printf("%2d: %lld\n", i, count);
}
#endif
}
void pic_init(void)
{
pic_init1(0x20, 0x4d0, &pics[0]);
pic_init1(0xa0, 0x4d1, &pics[1]);
pics[0].elcr_mask = 0xf8;
pics[1].elcr_mask = 0xde;
}

2297
hw/ide.c Normal file

File diff suppressed because it is too large Load Diff

602
hw/m48t59.c Normal file
View File

@@ -0,0 +1,602 @@
/*
* QEMU M48T59 NVRAM emulation for PPC PREP platform
*
* Copyright (c) 2003-2004 Jocelyn Mayer
*
* 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"
#include "m48t59.h"
//#define DEBUG_NVRAM
#if defined(DEBUG_NVRAM)
#define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
#else
#define NVRAM_PRINTF(fmt, args...) do { } while (0)
#endif
struct m48t59_t {
/* Hardware parameters */
int IRQ;
int mem_index;
uint32_t mem_base;
uint32_t io_base;
uint16_t size;
/* RTC management */
time_t time_offset;
time_t stop_time;
/* Alarm & watchdog */
time_t alarm;
struct QEMUTimer *alrm_timer;
struct QEMUTimer *wd_timer;
/* NVRAM storage */
uint8_t lock;
uint16_t addr;
uint8_t *buffer;
};
/* Fake timer functions */
/* Generic helpers for BCD */
static inline uint8_t toBCD (uint8_t value)
{
return (((value / 10) % 10) << 4) | (value % 10);
}
static inline uint8_t fromBCD (uint8_t BCD)
{
return ((BCD >> 4) * 10) + (BCD & 0x0F);
}
/* RTC management helpers */
static void get_time (m48t59_t *NVRAM, struct tm *tm)
{
time_t t;
t = time(NULL) + NVRAM->time_offset;
#ifdef _WIN32
memcpy(tm,localtime(&t),sizeof(*tm));
#else
localtime_r (&t, tm) ;
#endif
}
static void set_time (m48t59_t *NVRAM, struct tm *tm)
{
time_t now, new_time;
new_time = mktime(tm);
now = time(NULL);
NVRAM->time_offset = new_time - now;
}
/* Alarm management */
static void alarm_cb (void *opaque)
{
struct tm tm, tm_now;
uint64_t next_time;
m48t59_t *NVRAM = opaque;
pic_set_irq(NVRAM->IRQ, 1);
if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a month */
get_time(NVRAM, &tm_now);
memcpy(&tm, &tm_now, sizeof(struct tm));
tm.tm_mon++;
if (tm.tm_mon == 13) {
tm.tm_mon = 1;
tm.tm_year++;
}
next_time = mktime(&tm);
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a day */
next_time = 24 * 60 * 60 + mktime(&tm_now);
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once an hour */
next_time = 60 * 60 + mktime(&tm_now);
} else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
(NVRAM->buffer[0x1FF2] & 0x80) == 0) {
/* Repeat once a minute */
next_time = 60 + mktime(&tm_now);
} else {
/* Repeat once a second */
next_time = 1 + mktime(&tm_now);
}
qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000);
pic_set_irq(NVRAM->IRQ, 0);
}
static void get_alarm (m48t59_t *NVRAM, struct tm *tm)
{
#ifdef _WIN32
memcpy(tm,localtime(&NVRAM->alarm),sizeof(*tm));
#else
localtime_r (&NVRAM->alarm, tm);
#endif
}
static void set_alarm (m48t59_t *NVRAM, struct tm *tm)
{
NVRAM->alarm = mktime(tm);
if (NVRAM->alrm_timer != NULL) {
qemu_del_timer(NVRAM->alrm_timer);
NVRAM->alrm_timer = NULL;
}
if (NVRAM->alarm - time(NULL) > 0)
qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
}
/* Watchdog management */
static void watchdog_cb (void *opaque)
{
m48t59_t *NVRAM = opaque;
NVRAM->buffer[0x1FF0] |= 0x80;
if (NVRAM->buffer[0x1FF7] & 0x80) {
NVRAM->buffer[0x1FF7] = 0x00;
NVRAM->buffer[0x1FFC] &= ~0x40;
/* May it be a hw CPU Reset instead ? */
qemu_system_reset_request();
} else {
pic_set_irq(NVRAM->IRQ, 1);
pic_set_irq(NVRAM->IRQ, 0);
}
}
static void set_up_watchdog (m48t59_t *NVRAM, uint8_t value)
{
uint64_t interval; /* in 1/16 seconds */
if (NVRAM->wd_timer != NULL) {
qemu_del_timer(NVRAM->wd_timer);
NVRAM->wd_timer = NULL;
}
NVRAM->buffer[0x1FF0] &= ~0x80;
if (value != 0) {
interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
((interval * 1000) >> 4));
}
}
/* Direct access to NVRAM */
void m48t59_write (m48t59_t *NVRAM, uint32_t val)
{
struct tm tm;
int tmp;
if (NVRAM->addr > 0x1FF8 && NVRAM->addr < 0x2000)
NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val);
switch (NVRAM->addr) {
case 0x1FF0:
/* flags register : read-only */
break;
case 0x1FF1:
/* unused */
break;
case 0x1FF2:
/* alarm seconds */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_alarm(NVRAM, &tm);
tm.tm_sec = tmp;
NVRAM->buffer[0x1FF2] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF3:
/* alarm minutes */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_alarm(NVRAM, &tm);
tm.tm_min = tmp;
NVRAM->buffer[0x1FF3] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF4:
/* alarm hours */
tmp = fromBCD(val & 0x3F);
if (tmp >= 0 && tmp <= 23) {
get_alarm(NVRAM, &tm);
tm.tm_hour = tmp;
NVRAM->buffer[0x1FF4] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF5:
/* alarm date */
tmp = fromBCD(val & 0x1F);
if (tmp != 0) {
get_alarm(NVRAM, &tm);
tm.tm_mday = tmp;
NVRAM->buffer[0x1FF5] = val;
set_alarm(NVRAM, &tm);
}
break;
case 0x1FF6:
/* interrupts */
NVRAM->buffer[0x1FF6] = val;
break;
case 0x1FF7:
/* watchdog */
NVRAM->buffer[0x1FF7] = val;
set_up_watchdog(NVRAM, val);
break;
case 0x1FF8:
/* control */
NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
break;
case 0x1FF9:
/* seconds (BCD) */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm);
tm.tm_sec = tmp;
set_time(NVRAM, &tm);
}
if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) {
if (val & 0x80) {
NVRAM->stop_time = time(NULL);
} else {
NVRAM->time_offset += NVRAM->stop_time - time(NULL);
NVRAM->stop_time = 0;
}
}
NVRAM->buffer[0x1FF9] = val & 0x80;
break;
case 0x1FFA:
/* minutes (BCD) */
tmp = fromBCD(val & 0x7F);
if (tmp >= 0 && tmp <= 59) {
get_time(NVRAM, &tm);
tm.tm_min = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFB:
/* hours (BCD) */
tmp = fromBCD(val & 0x3F);
if (tmp >= 0 && tmp <= 23) {
get_time(NVRAM, &tm);
tm.tm_hour = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFC:
/* day of the week / century */
tmp = fromBCD(val & 0x07);
get_time(NVRAM, &tm);
tm.tm_wday = tmp;
set_time(NVRAM, &tm);
NVRAM->buffer[0x1FFC] = val & 0x40;
break;
case 0x1FFD:
/* date */
tmp = fromBCD(val & 0x1F);
if (tmp != 0) {
get_time(NVRAM, &tm);
tm.tm_mday = tmp;
set_time(NVRAM, &tm);
}
break;
case 0x1FFE:
/* month */
tmp = fromBCD(val & 0x1F);
if (tmp >= 1 && tmp <= 12) {
get_time(NVRAM, &tm);
tm.tm_mon = tmp - 1;
set_time(NVRAM, &tm);
}
break;
case 0x1FFF:
/* year */
tmp = fromBCD(val);
if (tmp >= 0 && tmp <= 99) {
get_time(NVRAM, &tm);
tm.tm_year = fromBCD(val);
set_time(NVRAM, &tm);
}
break;
default:
/* Check lock registers state */
if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
break;
if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
break;
if (NVRAM->addr < 0x1FF0 ||
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
NVRAM->buffer[NVRAM->addr] = val & 0xFF;
}
break;
}
}
uint32_t m48t59_read (m48t59_t *NVRAM)
{
struct tm tm;
uint32_t retval = 0xFF;
switch (NVRAM->addr) {
case 0x1FF0:
/* flags register */
goto do_read;
case 0x1FF1:
/* unused */
retval = 0;
break;
case 0x1FF2:
/* alarm seconds */
goto do_read;
case 0x1FF3:
/* alarm minutes */
goto do_read;
case 0x1FF4:
/* alarm hours */
goto do_read;
case 0x1FF5:
/* alarm date */
goto do_read;
case 0x1FF6:
/* interrupts */
goto do_read;
case 0x1FF7:
/* A read resets the watchdog */
set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
goto do_read;
case 0x1FF8:
/* control */
goto do_read;
case 0x1FF9:
/* seconds (BCD) */
get_time(NVRAM, &tm);
retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec);
break;
case 0x1FFA:
/* minutes (BCD) */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_min);
break;
case 0x1FFB:
/* hours (BCD) */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_hour);
break;
case 0x1FFC:
/* day of the week / century */
get_time(NVRAM, &tm);
retval = NVRAM->buffer[0x1FFC] | tm.tm_wday;
break;
case 0x1FFD:
/* date */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_mday);
break;
case 0x1FFE:
/* month */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_mon + 1);
break;
case 0x1FFF:
/* year */
get_time(NVRAM, &tm);
retval = toBCD(tm.tm_year);
break;
default:
/* Check lock registers state */
if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
break;
if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
break;
if (NVRAM->addr < 0x1FF0 ||
(NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
do_read:
retval = NVRAM->buffer[NVRAM->addr];
}
break;
}
if (NVRAM->addr > 0x1FF9 && NVRAM->addr < 0x2000)
NVRAM_PRINTF("0x%08x <= 0x%08x\n", NVRAM->addr, retval);
return retval;
}
void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr)
{
NVRAM->addr = addr;
}
void m48t59_toggle_lock (m48t59_t *NVRAM, int lock)
{
NVRAM->lock ^= 1 << lock;
}
/* IO access to NVRAM */
static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->io_base;
NVRAM_PRINTF("0x%08x => 0x%08x\n", addr, val);
switch (addr) {
case 0:
NVRAM->addr &= ~0x00FF;
NVRAM->addr |= val;
break;
case 1:
NVRAM->addr &= ~0xFF00;
NVRAM->addr |= val << 8;
break;
case 3:
m48t59_write(NVRAM, val);
NVRAM->addr = 0x0000;
break;
default:
break;
}
}
static uint32_t NVRAM_readb (void *opaque, uint32_t addr)
{
m48t59_t *NVRAM = opaque;
uint32_t retval;
addr -= NVRAM->io_base;
switch (addr) {
case 3:
retval = m48t59_read(NVRAM);
break;
default:
retval = -1;
break;
}
NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval);
return retval;
}
static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
if (addr < 0x1FF0)
NVRAM->buffer[addr] = value;
}
static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
if (addr < 0x1FF0) {
NVRAM->buffer[addr] = value >> 8;
NVRAM->buffer[addr + 1] = value;
}
}
static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
m48t59_t *NVRAM = opaque;
addr -= NVRAM->mem_base;
if (addr < 0x1FF0) {
NVRAM->buffer[addr] = value >> 24;
NVRAM->buffer[addr + 1] = value >> 16;
NVRAM->buffer[addr + 2] = value >> 8;
NVRAM->buffer[addr + 3] = value;
}
}
static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
{
m48t59_t *NVRAM = opaque;
uint32_t retval = 0;
addr -= NVRAM->mem_base;
if (addr < 0x1FF0)
retval = NVRAM->buffer[addr];
return retval;
}
static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
{
m48t59_t *NVRAM = opaque;
uint32_t retval = 0;
addr -= NVRAM->mem_base;
if (addr < 0x1FF0) {
retval = NVRAM->buffer[addr] << 8;
retval |= NVRAM->buffer[addr + 1];
}
return retval;
}
static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
{
m48t59_t *NVRAM = opaque;
uint32_t retval = 0;
addr -= NVRAM->mem_base;
if (addr < 0x1FF0) {
retval = NVRAM->buffer[addr] << 24;
retval |= NVRAM->buffer[addr + 1] << 16;
retval |= NVRAM->buffer[addr + 2] << 8;
retval |= NVRAM->buffer[addr + 3];
}
return retval;
}
static CPUWriteMemoryFunc *nvram_write[] = {
&nvram_writeb,
&nvram_writew,
&nvram_writel,
};
static CPUReadMemoryFunc *nvram_read[] = {
&nvram_readb,
&nvram_readw,
&nvram_readl,
};
/* Initialisation routine */
m48t59_t *m48t59_init (int IRQ, uint32_t mem_base,
uint32_t io_base, uint16_t size)
{
m48t59_t *s;
s = qemu_mallocz(sizeof(m48t59_t));
if (!s)
return NULL;
s->buffer = qemu_mallocz(size);
if (!s->buffer) {
qemu_free(s);
return NULL;
}
s->IRQ = IRQ;
s->size = size;
s->mem_base = mem_base;
s->io_base = io_base;
s->addr = 0;
register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s);
register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s);
if (mem_base != 0) {
s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
}
s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s);
s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s);
s->lock = 0;
return s;
}

13
hw/m48t59.h Normal file
View File

@@ -0,0 +1,13 @@
#if !defined (__M48T59_H__)
#define __M48T59_H__
typedef struct m48t59_t m48t59_t;
void m48t59_write (m48t59_t *NVRAM, uint32_t val);
uint32_t m48t59_read (m48t59_t *NVRAM);
void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr);
void m48t59_toggle_lock (m48t59_t *NVRAM, int lock);
m48t59_t *m48t59_init (int IRQ, uint32_t io_base,
uint32_t mem_base, uint16_t size);
#endif /* !defined (__M48T59_H__) */

463
hw/mc146818rtc.c Normal file
View File

@@ -0,0 +1,463 @@
/*
* QEMU MC146818 RTC emulation
*
* Copyright (c) 2003-2004 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"
//#define DEBUG_CMOS
#define RTC_SECONDS 0
#define RTC_SECONDS_ALARM 1
#define RTC_MINUTES 2
#define RTC_MINUTES_ALARM 3
#define RTC_HOURS 4
#define RTC_HOURS_ALARM 5
#define RTC_ALARM_DONT_CARE 0xC0
#define RTC_DAY_OF_WEEK 6
#define RTC_DAY_OF_MONTH 7
#define RTC_MONTH 8
#define RTC_YEAR 9
#define RTC_REG_A 10
#define RTC_REG_B 11
#define RTC_REG_C 12
#define RTC_REG_D 13
#define REG_A_UIP 0x80
#define REG_B_SET 0x80
#define REG_B_PIE 0x40
#define REG_B_AIE 0x20
#define REG_B_UIE 0x10
struct RTCState {
uint8_t cmos_data[128];
uint8_t cmos_index;
struct tm current_tm;
int irq;
/* periodic timer */
QEMUTimer *periodic_timer;
int64_t next_periodic_time;
/* second update */
int64_t next_second_time;
QEMUTimer *second_timer;
QEMUTimer *second_timer2;
};
static void rtc_set_time(RTCState *s);
static void rtc_copy_date(RTCState *s);
static void rtc_timer_update(RTCState *s, int64_t current_time)
{
int period_code, period;
int64_t cur_clock, next_irq_clock;
period_code = s->cmos_data[RTC_REG_A] & 0x0f;
if (period_code != 0 &&
(s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
if (period_code <= 2)
period_code += 7;
/* period in 32 Khz cycles */
period = 1 << (period_code - 1);
/* compute 32 khz clock */
cur_clock = muldiv64(current_time, 32768, ticks_per_sec);
next_irq_clock = (cur_clock & ~(period - 1)) + period;
s->next_periodic_time = muldiv64(next_irq_clock, ticks_per_sec, 32768) + 1;
qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
} else {
qemu_del_timer(s->periodic_timer);
}
}
static void rtc_periodic_timer(void *opaque)
{
RTCState *s = opaque;
rtc_timer_update(s, s->next_periodic_time);
s->cmos_data[RTC_REG_C] |= 0xc0;
pic_set_irq(s->irq, 1);
}
static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
{
RTCState *s = opaque;
if ((addr & 1) == 0) {
s->cmos_index = data & 0x7f;
} else {
#ifdef DEBUG_CMOS
printf("cmos: write index=0x%02x val=0x%02x\n",
s->cmos_index, data);
#endif
switch(s->cmos_index) {
case RTC_SECONDS_ALARM:
case RTC_MINUTES_ALARM:
case RTC_HOURS_ALARM:
/* XXX: not supported */
s->cmos_data[s->cmos_index] = data;
break;
case RTC_SECONDS:
case RTC_MINUTES:
case RTC_HOURS:
case RTC_DAY_OF_WEEK:
case RTC_DAY_OF_MONTH:
case RTC_MONTH:
case RTC_YEAR:
s->cmos_data[s->cmos_index] = data;
/* if in set mode, do not update the time */
if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
rtc_set_time(s);
}
break;
case RTC_REG_A:
/* UIP bit is read only */
s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
(s->cmos_data[RTC_REG_A] & REG_A_UIP);
rtc_timer_update(s, qemu_get_clock(vm_clock));
break;
case RTC_REG_B:
if (data & REG_B_SET) {
/* set mode: reset UIP mode */
s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
data &= ~REG_B_UIE;
} else {
/* if disabling set mode, update the time */
if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
rtc_set_time(s);
}
}
s->cmos_data[RTC_REG_B] = data;
rtc_timer_update(s, qemu_get_clock(vm_clock));
break;
case RTC_REG_C:
case RTC_REG_D:
/* cannot write to them */
break;
default:
s->cmos_data[s->cmos_index] = data;
break;
}
}
}
static inline int to_bcd(RTCState *s, int a)
{
if (s->cmos_data[RTC_REG_B] & 0x04) {
return a;
} else {
return ((a / 10) << 4) | (a % 10);
}
}
static inline int from_bcd(RTCState *s, int a)
{
if (s->cmos_data[RTC_REG_B] & 0x04) {
return a;
} else {
return ((a >> 4) * 10) + (a & 0x0f);
}
}
static void rtc_set_time(RTCState *s)
{
struct tm *tm = &s->current_tm;
tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
(s->cmos_data[RTC_HOURS] & 0x80)) {
tm->tm_hour += 12;
}
tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]);
tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
}
static void rtc_copy_date(RTCState *s)
{
const struct tm *tm = &s->current_tm;
s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
if (s->cmos_data[RTC_REG_B] & 0x02) {
/* 24 hour format */
s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
} else {
/* 12 hour format */
s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
if (tm->tm_hour >= 12)
s->cmos_data[RTC_HOURS] |= 0x80;
}
s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
}
/* month is between 0 and 11. */
static int get_days_in_month(int month, int year)
{
static const int days_tab[12] = {
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
int d;
if ((unsigned )month >= 12)
return 31;
d = days_tab[month];
if (month == 1) {
if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
d++;
}
return d;
}
/* update 'tm' to the next second */
static void rtc_next_second(struct tm *tm)
{
int days_in_month;
tm->tm_sec++;
if ((unsigned)tm->tm_sec >= 60) {
tm->tm_sec = 0;
tm->tm_min++;
if ((unsigned)tm->tm_min >= 60) {
tm->tm_min = 0;
tm->tm_hour++;
if ((unsigned)tm->tm_hour >= 24) {
tm->tm_hour = 0;
/* next day */
tm->tm_wday++;
if ((unsigned)tm->tm_wday >= 7)
tm->tm_wday = 0;
days_in_month = get_days_in_month(tm->tm_mon,
tm->tm_year + 1900);
tm->tm_mday++;
if (tm->tm_mday < 1) {
tm->tm_mday = 1;
} else if (tm->tm_mday > days_in_month) {
tm->tm_mday = 1;
tm->tm_mon++;
if (tm->tm_mon >= 12) {
tm->tm_mon = 0;
tm->tm_year++;
}
}
}
}
}
}
static void rtc_update_second(void *opaque)
{
RTCState *s = opaque;
int64_t delay;
/* if the oscillator is not in normal operation, we do not update */
if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
s->next_second_time += ticks_per_sec;
qemu_mod_timer(s->second_timer, s->next_second_time);
} else {
rtc_next_second(&s->current_tm);
if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
/* update in progress bit */
s->cmos_data[RTC_REG_A] |= REG_A_UIP;
}
/* should be 244 us = 8 / 32768 seconds, but currently the
timers do not have the necessary resolution. */
delay = (ticks_per_sec * 1) / 100;
if (delay < 1)
delay = 1;
qemu_mod_timer(s->second_timer2,
s->next_second_time + delay);
}
}
static void rtc_update_second2(void *opaque)
{
RTCState *s = opaque;
if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
rtc_copy_date(s);
}
/* check alarm */
if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
s->cmos_data[RTC_REG_C] |= 0xa0;
pic_set_irq(s->irq, 1);
}
}
/* update ended interrupt */
if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
s->cmos_data[RTC_REG_C] |= 0x90;
pic_set_irq(s->irq, 1);
}
/* clear update in progress bit */
s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
s->next_second_time += ticks_per_sec;
qemu_mod_timer(s->second_timer, s->next_second_time);
}
static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
{
RTCState *s = opaque;
int ret;
if ((addr & 1) == 0) {
return 0xff;
} else {
switch(s->cmos_index) {
case RTC_SECONDS:
case RTC_MINUTES:
case RTC_HOURS:
case RTC_DAY_OF_WEEK:
case RTC_DAY_OF_MONTH:
case RTC_MONTH:
case RTC_YEAR:
ret = s->cmos_data[s->cmos_index];
break;
case RTC_REG_A:
ret = s->cmos_data[s->cmos_index];
break;
case RTC_REG_C:
ret = s->cmos_data[s->cmos_index];
pic_set_irq(s->irq, 0);
s->cmos_data[RTC_REG_C] = 0x00;
break;
default:
ret = s->cmos_data[s->cmos_index];
break;
}
#ifdef DEBUG_CMOS
printf("cmos: read index=0x%02x val=0x%02x\n",
s->cmos_index, ret);
#endif
return ret;
}
}
void rtc_set_memory(RTCState *s, int addr, int val)
{
if (addr >= 0 && addr <= 127)
s->cmos_data[addr] = val;
}
void rtc_set_date(RTCState *s, const struct tm *tm)
{
s->current_tm = *tm;
rtc_copy_date(s);
}
static void rtc_save(QEMUFile *f, void *opaque)
{
RTCState *s = opaque;
qemu_put_buffer(f, s->cmos_data, 128);
qemu_put_8s(f, &s->cmos_index);
qemu_put_be32s(f, &s->current_tm.tm_sec);
qemu_put_be32s(f, &s->current_tm.tm_min);
qemu_put_be32s(f, &s->current_tm.tm_hour);
qemu_put_be32s(f, &s->current_tm.tm_wday);
qemu_put_be32s(f, &s->current_tm.tm_mday);
qemu_put_be32s(f, &s->current_tm.tm_mon);
qemu_put_be32s(f, &s->current_tm.tm_year);
qemu_put_timer(f, s->periodic_timer);
qemu_put_be64s(f, &s->next_periodic_time);
qemu_put_be64s(f, &s->next_second_time);
qemu_put_timer(f, s->second_timer);
qemu_put_timer(f, s->second_timer2);
}
static int rtc_load(QEMUFile *f, void *opaque, int version_id)
{
RTCState *s = opaque;
if (version_id != 1)
return -EINVAL;
qemu_get_buffer(f, s->cmos_data, 128);
qemu_get_8s(f, &s->cmos_index);
qemu_get_be32s(f, &s->current_tm.tm_sec);
qemu_get_be32s(f, &s->current_tm.tm_min);
qemu_get_be32s(f, &s->current_tm.tm_hour);
qemu_get_be32s(f, &s->current_tm.tm_wday);
qemu_get_be32s(f, &s->current_tm.tm_mday);
qemu_get_be32s(f, &s->current_tm.tm_mon);
qemu_get_be32s(f, &s->current_tm.tm_year);
qemu_get_timer(f, s->periodic_timer);
qemu_get_be64s(f, &s->next_periodic_time);
qemu_get_be64s(f, &s->next_second_time);
qemu_get_timer(f, s->second_timer);
qemu_get_timer(f, s->second_timer2);
return 0;
}
RTCState *rtc_init(int base, int irq)
{
RTCState *s;
s = qemu_mallocz(sizeof(RTCState));
if (!s)
return NULL;
s->irq = irq;
s->cmos_data[RTC_REG_A] = 0x26;
s->cmos_data[RTC_REG_B] = 0x02;
s->cmos_data[RTC_REG_C] = 0x00;
s->cmos_data[RTC_REG_D] = 0x80;
s->periodic_timer = qemu_new_timer(vm_clock,
rtc_periodic_timer, s);
s->second_timer = qemu_new_timer(vm_clock,
rtc_update_second, s);
s->second_timer2 = qemu_new_timer(vm_clock,
rtc_update_second2, s);
s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
qemu_mod_timer(s->second_timer2, s->next_second_time);
register_ioport_write(base, 2, 1, cmos_ioport_write, s);
register_ioport_read(base, 2, 1, cmos_ioport_read, s);
register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
return s;
}

623
hw/ne2000.c Normal file
View File

@@ -0,0 +1,623 @@
/*
* QEMU NE2000 emulation
*
* Copyright (c) 2003-2004 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 NE2000 card */
//#define DEBUG_NE2000
#define MAX_ETH_FRAME_SIZE 1514
#define E8390_CMD 0x00 /* The command register (for all pages) */
/* Page 0 register offsets. */
#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */
#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */
#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */
#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */
#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */
#define EN0_TSR 0x04 /* Transmit status reg RD */
#define EN0_TPSR 0x04 /* Transmit starting page WR */
#define EN0_NCR 0x05 /* Number of collision reg RD */
#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */
#define EN0_FIFO 0x06 /* FIFO RD */
#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */
#define EN0_ISR 0x07 /* Interrupt status reg RD WR */
#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */
#define EN0_RSARLO 0x08 /* Remote start address reg 0 */
#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */
#define EN0_RSARHI 0x09 /* Remote start address reg 1 */
#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */
#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */
#define EN0_RSR 0x0c /* rx status reg RD */
#define EN0_RXCR 0x0c /* RX configuration reg WR */
#define EN0_TXCR 0x0d /* TX configuration reg WR */
#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */
#define EN0_DCFG 0x0e /* Data configuration reg WR */
#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */
#define EN0_IMR 0x0f /* Interrupt mask reg WR */
#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */
#define EN1_PHYS 0x11
#define EN1_CURPAG 0x17
#define EN1_MULT 0x18
/* Register accessed at EN_CMD, the 8390 base addr. */
#define E8390_STOP 0x01 /* Stop and reset the chip */
#define E8390_START 0x02 /* Start the chip, clear reset */
#define E8390_TRANS 0x04 /* Transmit a frame */
#define E8390_RREAD 0x08 /* Remote read */
#define E8390_RWRITE 0x10 /* Remote write */
#define E8390_NODMA 0x20 /* Remote DMA */
#define E8390_PAGE0 0x00 /* Select page chip registers */
#define E8390_PAGE1 0x40 /* using the two high-order bits */
#define E8390_PAGE2 0x80 /* Page 3 is invalid. */
/* Bits in EN0_ISR - Interrupt status register */
#define ENISR_RX 0x01 /* Receiver, no error */
#define ENISR_TX 0x02 /* Transmitter, no error */
#define ENISR_RX_ERR 0x04 /* Receiver, with error */
#define ENISR_TX_ERR 0x08 /* Transmitter, with error */
#define ENISR_OVER 0x10 /* Receiver overwrote the ring */
#define ENISR_COUNTERS 0x20 /* Counters need emptying */
#define ENISR_RDC 0x40 /* remote dma complete */
#define ENISR_RESET 0x80 /* Reset completed */
#define ENISR_ALL 0x3f /* Interrupts we will enable */
/* Bits in received packet status byte and EN0_RSR*/
#define ENRSR_RXOK 0x01 /* Received a good packet */
#define ENRSR_CRC 0x02 /* CRC error */
#define ENRSR_FAE 0x04 /* frame alignment error */
#define ENRSR_FO 0x08 /* FIFO overrun */
#define ENRSR_MPA 0x10 /* missed pkt */
#define ENRSR_PHY 0x20 /* physical/multicast address */
#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */
#define ENRSR_DEF 0x80 /* deferring */
/* Transmitted packet status, EN0_TSR. */
#define ENTSR_PTX 0x01 /* Packet transmitted without error */
#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */
#define ENTSR_COL 0x04 /* The transmit collided at least once. */
#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */
#define ENTSR_CRS 0x10 /* The carrier sense was lost. */
#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */
#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */
#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */
#define NE2000_PMEM_SIZE (32*1024)
#define NE2000_PMEM_START (16*1024)
#define NE2000_PMEM_END (NE2000_PMEM_SIZE+NE2000_PMEM_START)
#define NE2000_MEM_SIZE NE2000_PMEM_END
typedef struct NE2000State {
uint8_t cmd;
uint32_t start;
uint32_t stop;
uint8_t boundary;
uint8_t tsr;
uint8_t tpsr;
uint16_t tcnt;
uint16_t rcnt;
uint32_t rsar;
uint8_t rsr;
uint8_t isr;
uint8_t dcfg;
uint8_t imr;
uint8_t phys[6]; /* mac address */
uint8_t curpag;
uint8_t mult[8]; /* multicast mask array */
int irq;
PCIDevice *pci_dev;
NetDriverState *nd;
uint8_t mem[NE2000_MEM_SIZE];
} NE2000State;
static void ne2000_reset(NE2000State *s)
{
int i;
s->isr = ENISR_RESET;
memcpy(s->mem, s->nd->macaddr, 6);
s->mem[14] = 0x57;
s->mem[15] = 0x57;
/* duplicate prom data */
for(i = 15;i >= 0; i--) {
s->mem[2 * i] = s->mem[i];
s->mem[2 * i + 1] = s->mem[i];
}
}
static void ne2000_update_irq(NE2000State *s)
{
int isr;
isr = s->isr & s->imr;
#if defined(DEBUG_NE2000)
printf("NE2000: Set IRQ line %d to %d (%02x %02x)\n",
s->irq, isr ? 1 : 0, s->isr, s->imr);
#endif
if (s->irq == 16) {
/* PCI irq */
pci_set_irq(s->pci_dev, 0, (isr != 0));
} else {
/* ISA irq */
pic_set_irq(s->irq, (isr != 0));
}
}
/* return the max buffer size if the NE2000 can receive more data */
static int ne2000_can_receive(void *opaque)
{
NE2000State *s = opaque;
int avail, index, boundary;
if (s->cmd & E8390_STOP)
return 0;
index = s->curpag << 8;
boundary = s->boundary << 8;
if (index < boundary)
avail = boundary - index;
else
avail = (s->stop - s->start) - (index - boundary);
if (avail < (MAX_ETH_FRAME_SIZE + 4))
return 0;
return MAX_ETH_FRAME_SIZE;
}
#define MIN_BUF_SIZE 60
static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
{
NE2000State *s = opaque;
uint8_t *p;
int total_len, next, avail, len, index;
uint8_t buf1[60];
#if defined(DEBUG_NE2000)
printf("NE2000: received len=%d\n", size);
#endif
/* if too small buffer, then expand it */
if (size < MIN_BUF_SIZE) {
memcpy(buf1, buf, size);
memset(buf1 + size, 0, MIN_BUF_SIZE - size);
buf = buf1;
size = MIN_BUF_SIZE;
}
index = s->curpag << 8;
/* 4 bytes for header */
total_len = size + 4;
/* address for next packet (4 bytes for CRC) */
next = index + ((total_len + 4 + 255) & ~0xff);
if (next >= s->stop)
next -= (s->stop - s->start);
/* prepare packet header */
p = s->mem + index;
s->rsr = ENRSR_RXOK; /* receive status */
/* XXX: check this */
if (buf[0] & 0x01)
s->rsr |= ENRSR_PHY;
p[0] = s->rsr;
p[1] = next >> 8;
p[2] = total_len;
p[3] = total_len >> 8;
index += 4;
/* write packet data */
while (size > 0) {
avail = s->stop - index;
len = size;
if (len > avail)
len = avail;
memcpy(s->mem + index, buf, len);
buf += len;
index += len;
if (index == s->stop)
index = s->start;
size -= len;
}
s->curpag = next >> 8;
/* now we can signal we have receive something */
s->isr |= ENISR_RX;
ne2000_update_irq(s);
}
static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
NE2000State *s = opaque;
int offset, page;
addr &= 0xf;
#ifdef DEBUG_NE2000
printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
#endif
if (addr == E8390_CMD) {
/* control register */
s->cmd = val;
if (val & E8390_START) {
s->isr &= ~ENISR_RESET;
/* test specific case: zero length transfert */
if ((val & (E8390_RREAD | E8390_RWRITE)) &&
s->rcnt == 0) {
s->isr |= ENISR_RDC;
ne2000_update_irq(s);
}
if (val & E8390_TRANS) {
qemu_send_packet(s->nd, s->mem + (s->tpsr << 8), s->tcnt);
/* signal end of transfert */
s->tsr = ENTSR_PTX;
s->isr |= ENISR_TX;
ne2000_update_irq(s);
}
}
} else {
page = s->cmd >> 6;
offset = addr | (page << 4);
switch(offset) {
case EN0_STARTPG:
s->start = val << 8;
break;
case EN0_STOPPG:
s->stop = val << 8;
break;
case EN0_BOUNDARY:
s->boundary = val;
break;
case EN0_IMR:
s->imr = val;
ne2000_update_irq(s);
break;
case EN0_TPSR:
s->tpsr = val;
break;
case EN0_TCNTLO:
s->tcnt = (s->tcnt & 0xff00) | val;
break;
case EN0_TCNTHI:
s->tcnt = (s->tcnt & 0x00ff) | (val << 8);
break;
case EN0_RSARLO:
s->rsar = (s->rsar & 0xff00) | val;
break;
case EN0_RSARHI:
s->rsar = (s->rsar & 0x00ff) | (val << 8);
break;
case EN0_RCNTLO:
s->rcnt = (s->rcnt & 0xff00) | val;
break;
case EN0_RCNTHI:
s->rcnt = (s->rcnt & 0x00ff) | (val << 8);
break;
case EN0_DCFG:
s->dcfg = val;
break;
case EN0_ISR:
s->isr &= ~(val & 0x7f);
ne2000_update_irq(s);
break;
case EN1_PHYS ... EN1_PHYS + 5:
s->phys[offset - EN1_PHYS] = val;
break;
case EN1_CURPAG:
s->curpag = val;
break;
case EN1_MULT ... EN1_MULT + 7:
s->mult[offset - EN1_MULT] = val;
break;
}
}
}
static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr)
{
NE2000State *s = opaque;
int offset, page, ret;
addr &= 0xf;
if (addr == E8390_CMD) {
ret = s->cmd;
} else {
page = s->cmd >> 6;
offset = addr | (page << 4);
switch(offset) {
case EN0_TSR:
ret = s->tsr;
break;
case EN0_BOUNDARY:
ret = s->boundary;
break;
case EN0_ISR:
ret = s->isr;
break;
case EN0_RSARLO:
ret = s->rsar & 0x00ff;
break;
case EN0_RSARHI:
ret = s->rsar >> 8;
break;
case EN1_PHYS ... EN1_PHYS + 5:
ret = s->phys[offset - EN1_PHYS];
break;
case EN1_CURPAG:
ret = s->curpag;
break;
case EN1_MULT ... EN1_MULT + 7:
ret = s->mult[offset - EN1_MULT];
break;
case EN0_RSR:
ret = s->rsr;
break;
default:
ret = 0x00;
break;
}
}
#ifdef DEBUG_NE2000
printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);
#endif
return ret;
}
static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr,
uint32_t val)
{
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
s->mem[addr] = val;
}
}
static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr,
uint32_t val)
{
addr &= ~1; /* XXX: check exact behaviour if not even */
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
*(uint16_t *)(s->mem + addr) = cpu_to_le16(val);
}
}
static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr,
uint32_t val)
{
addr &= ~1; /* XXX: check exact behaviour if not even */
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
cpu_to_le32wu((uint32_t *)(s->mem + addr), val);
}
}
static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr)
{
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
return s->mem[addr];
} else {
return 0xff;
}
}
static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr)
{
addr &= ~1; /* XXX: check exact behaviour if not even */
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
return le16_to_cpu(*(uint16_t *)(s->mem + addr));
} else {
return 0xffff;
}
}
static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr)
{
addr &= ~1; /* XXX: check exact behaviour if not even */
if (addr < 32 ||
(addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
return le32_to_cpupu((uint32_t *)(s->mem + addr));
} else {
return 0xffffffff;
}
}
static inline void ne2000_dma_update(NE2000State *s, int len)
{
s->rsar += len;
/* wrap */
/* XXX: check what to do if rsar > stop */
if (s->rsar == s->stop)
s->rsar = s->start;
if (s->rcnt <= len) {
s->rcnt = 0;
/* signal end of transfert */
s->isr |= ENISR_RDC;
ne2000_update_irq(s);
} else {
s->rcnt -= len;
}
}
static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
NE2000State *s = opaque;
#ifdef DEBUG_NE2000
printf("NE2000: asic write val=0x%04x\n", val);
#endif
if (s->rcnt == 0)
return;
if (s->dcfg & 0x01) {
/* 16 bit access */
ne2000_mem_writew(s, s->rsar, val);
ne2000_dma_update(s, 2);
} else {
/* 8 bit access */
ne2000_mem_writeb(s, s->rsar, val);
ne2000_dma_update(s, 1);
}
}
static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr)
{
NE2000State *s = opaque;
int ret;
if (s->dcfg & 0x01) {
/* 16 bit access */
ret = ne2000_mem_readw(s, s->rsar);
ne2000_dma_update(s, 2);
} else {
/* 8 bit access */
ret = ne2000_mem_readb(s, s->rsar);
ne2000_dma_update(s, 1);
}
#ifdef DEBUG_NE2000
printf("NE2000: asic read val=0x%04x\n", ret);
#endif
return ret;
}
static void ne2000_asic_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
{
NE2000State *s = opaque;
#ifdef DEBUG_NE2000
printf("NE2000: asic writel val=0x%04x\n", val);
#endif
if (s->rcnt == 0)
return;
/* 32 bit access */
ne2000_mem_writel(s, s->rsar, val);
ne2000_dma_update(s, 4);
}
static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr)
{
NE2000State *s = opaque;
int ret;
/* 32 bit access */
ret = ne2000_mem_readl(s, s->rsar);
ne2000_dma_update(s, 4);
#ifdef DEBUG_NE2000
printf("NE2000: asic readl val=0x%04x\n", ret);
#endif
return ret;
}
static void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
/* nothing to do (end of reset pulse) */
}
static uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr)
{
NE2000State *s = opaque;
ne2000_reset(s);
return 0;
}
void isa_ne2000_init(int base, int irq, NetDriverState *nd)
{
NE2000State *s;
s = qemu_mallocz(sizeof(NE2000State));
if (!s)
return;
register_ioport_write(base, 16, 1, ne2000_ioport_write, s);
register_ioport_read(base, 16, 1, ne2000_ioport_read, s);
register_ioport_write(base + 0x10, 1, 1, ne2000_asic_ioport_write, s);
register_ioport_read(base + 0x10, 1, 1, ne2000_asic_ioport_read, s);
register_ioport_write(base + 0x10, 2, 2, ne2000_asic_ioport_write, s);
register_ioport_read(base + 0x10, 2, 2, ne2000_asic_ioport_read, s);
register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
s->irq = irq;
s->nd = nd;
ne2000_reset(s);
qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s);
}
/***********************************************************/
/* PCI NE2000 definitions */
typedef struct PCINE2000State {
PCIDevice dev;
NE2000State ne2000;
} PCINE2000State;
static void ne2000_map(PCIDevice *pci_dev, int region_num,
uint32_t addr, uint32_t size, int type)
{
PCINE2000State *d = (PCINE2000State *)pci_dev;
NE2000State *s = &d->ne2000;
register_ioport_write(addr, 16, 1, ne2000_ioport_write, s);
register_ioport_read(addr, 16, 1, ne2000_ioport_read, s);
register_ioport_write(addr + 0x10, 1, 1, ne2000_asic_ioport_write, s);
register_ioport_read(addr + 0x10, 1, 1, ne2000_asic_ioport_read, s);
register_ioport_write(addr + 0x10, 2, 2, ne2000_asic_ioport_write, s);
register_ioport_read(addr + 0x10, 2, 2, ne2000_asic_ioport_read, s);
register_ioport_write(addr + 0x10, 4, 4, ne2000_asic_ioport_writel, s);
register_ioport_read(addr + 0x10, 4, 4, ne2000_asic_ioport_readl, s);
register_ioport_write(addr + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
}
void pci_ne2000_init(PCIBus *bus, NetDriverState *nd)
{
PCINE2000State *d;
NE2000State *s;
uint8_t *pci_conf;
d = (PCINE2000State *)pci_register_device(bus,
"NE2000", sizeof(PCINE2000State),
-1,
NULL, NULL);
pci_conf = d->dev.config;
pci_conf[0x00] = 0xec; // Realtek 8029
pci_conf[0x01] = 0x10;
pci_conf[0x02] = 0x29;
pci_conf[0x03] = 0x80;
pci_conf[0x0a] = 0x00; // ethernet network controller
pci_conf[0x0b] = 0x02;
pci_conf[0x0e] = 0x00; // header_type
pci_conf[0x3d] = 1; // interrupt pin 0
pci_register_io_region((PCIDevice *)d, 0, 0x100,
PCI_ADDRESS_SPACE_IO, ne2000_map);
s = &d->ne2000;
s->irq = 16; // PCI interrupt
s->pci_dev = (PCIDevice *)d;
s->nd = nd;
ne2000_reset(s);
qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s);
}

1023
hw/openpic.c Normal file

File diff suppressed because it is too large Load Diff

516
hw/pc.c Normal file
View File

@@ -0,0 +1,516 @@
/*
* QEMU PC System Emulator
*
* Copyright (c) 2003-2004 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"
/* output Bochs bios info messages */
//#define DEBUG_BIOS
#define BIOS_FILENAME "bios.bin"
#define VGABIOS_FILENAME "vgabios.bin"
#define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin"
#define LINUX_BOOT_FILENAME "linux_boot.bin"
#define KERNEL_LOAD_ADDR 0x00100000
#define INITRD_LOAD_ADDR 0x00400000
#define KERNEL_PARAMS_ADDR 0x00090000
#define KERNEL_CMDLINE_ADDR 0x00099000
int speaker_data_on;
int dummy_refresh_clock;
static fdctrl_t *floppy_controller;
static RTCState *rtc_state;
static PITState *pit;
static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
{
}
/* MSDOS compatibility mode FPU exception support */
/* XXX: add IGNNE support */
void cpu_set_ferr(CPUX86State *s)
{
pic_set_irq(13, 1);
}
static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data)
{
pic_set_irq(13, 0);
}
/* TSC handling */
uint64_t cpu_get_tsc(CPUX86State *env)
{
return qemu_get_clock(vm_clock);
}
/* 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)
{
int val;
switch (fd0) {
case 0:
/* 1.44 Mb 3"5 drive */
val = 4;
break;
case 1:
/* 2.88 Mb 3"5 drive */
val = 5;
break;
case 2:
/* 1.2 Mb 5"5 drive */
val = 2;
break;
default:
val = 0;
break;
}
return val;
}
static void cmos_init(int ram_size, int boot_device)
{
RTCState *s = rtc_state;
int val;
int fd0, fd1, nb;
time_t ti;
struct tm *tm;
/* 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 */
val = 640; /* base memory in K */
rtc_set_memory(s, 0x15, val);
rtc_set_memory(s, 0x16, val >> 8);
val = (ram_size / 1024) - 1024;
if (val > 65535)
val = 65535;
rtc_set_memory(s, 0x17, val);
rtc_set_memory(s, 0x18, val >> 8);
rtc_set_memory(s, 0x30, val);
rtc_set_memory(s, 0x31, val >> 8);
if (ram_size > (16 * 1024 * 1024))
val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536);
else
val = 0;
if (val > 65535)
val = 65535;
rtc_set_memory(s, 0x34, val);
rtc_set_memory(s, 0x35, val >> 8);
switch(boot_device) {
case 'a':
case 'b':
rtc_set_memory(s, 0x3d, 0x01); /* floppy boot */
break;
default:
case 'c':
rtc_set_memory(s, 0x3d, 0x02); /* hard drive boot */
break;
case 'd':
rtc_set_memory(s, 0x3d, 0x03); /* CD-ROM boot */
break;
}
/* floppy type */
fd0 = fdctrl_get_drive_type(floppy_controller, 0);
fd1 = fdctrl_get_drive_type(floppy_controller, 1);
val = (cmos_get_fd_drive_type(fd0) << 4) | cmos_get_fd_drive_type(fd1);
rtc_set_memory(s, 0x10, val);
val = 0;
nb = 0;
if (fd0 < 3)
nb++;
if (fd1 < 3)
nb++;
switch (nb) {
case 0:
break;
case 1:
val |= 0x01; /* 1 drive, ready for boot */
break;
case 2:
val |= 0x41; /* 2 drives, ready for boot */
break;
}
val |= 0x02; /* FPU is there */
val |= 0x04; /* PS/2 mouse installed */
rtc_set_memory(s, REG_EQUIPMENT_BYTE, val);
}
static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
speaker_data_on = (val >> 1) & 1;
pit_set_gate(pit, 2, val & 1);
}
static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
{
int out;
out = pit_get_out(pit, 2, qemu_get_clock(vm_clock));
dummy_refresh_clock ^= 1;
return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
(dummy_refresh_clock << 4);
}
static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
{
cpu_x86_set_a20(cpu_single_env, (val >> 1) & 1);
/* XXX: bit 0 is fast reset */
}
static uint32_t ioport92_read(void *opaque, uint32_t addr)
{
return ((cpu_single_env->a20_mask >> 20) & 1) << 1;
}
/***********************************************************/
/* Bochs BIOS debug ports */
void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val)
{
static const char shutdown_str[8] = "Shutdown";
static int shutdown_index = 0;
switch(addr) {
/* Bochs BIOS messages */
case 0x400:
case 0x401:
fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val);
exit(1);
case 0x402:
case 0x403:
#ifdef DEBUG_BIOS
fprintf(stderr, "%c", val);
#endif
break;
case 0x8900:
/* same as Bochs power off */
if (val == shutdown_str[shutdown_index]) {
shutdown_index++;
if (shutdown_index == 8) {
shutdown_index = 0;
qemu_system_shutdown_request();
}
} else {
shutdown_index = 0;
}
break;
/* LGPL'ed VGA BIOS messages */
case 0x501:
case 0x502:
fprintf(stderr, "VGA BIOS panic, line %d\n", val);
exit(1);
case 0x500:
case 0x503:
#ifdef DEBUG_BIOS
fprintf(stderr, "%c", val);
#endif
break;
}
}
void bochs_bios_init(void)
{
register_ioport_write(0x400, 1, 2, bochs_bios_write, NULL);
register_ioport_write(0x401, 1, 2, bochs_bios_write, NULL);
register_ioport_write(0x402, 1, 1, bochs_bios_write, NULL);
register_ioport_write(0x403, 1, 1, bochs_bios_write, NULL);
register_ioport_write(0x8900, 1, 1, bochs_bios_write, NULL);
register_ioport_write(0x501, 1, 2, bochs_bios_write, NULL);
register_ioport_write(0x502, 1, 2, bochs_bios_write, NULL);
register_ioport_write(0x500, 1, 1, bochs_bios_write, NULL);
register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL);
}
int load_kernel(const char *filename, uint8_t *addr,
uint8_t *real_addr)
{
int fd, size;
int setup_sects;
fd = open(filename, O_RDONLY);
if (fd < 0)
return -1;
/* load 16 bit code */
if (read(fd, real_addr, 512) != 512)
goto fail;
setup_sects = real_addr[0x1F1];
if (!setup_sects)
setup_sects = 4;
if (read(fd, real_addr + 512, setup_sects * 512) !=
setup_sects * 512)
goto fail;
/* load 32 bit code */
size = read(fd, addr, 16 * 1024 * 1024);
if (size < 0)
goto fail;
close(fd);
return size;
fail:
close(fd);
return -1;
}
static const int ide_iobase[2] = { 0x1f0, 0x170 };
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
static const int ide_irq[2] = { 14, 15 };
#define NE2000_NB_MAX 6
static uint32_t ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
/* PC hardware initialisation */
void pc_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];
int ret, linux_boot, initrd_size, i, nb_nics1, fd;
unsigned long bios_offset, vga_bios_offset;
int bios_size, isa_bios_size;
PCIBus *pci_bus;
linux_boot = (kernel_filename != NULL);
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, 0);
/* BIOS load */
bios_offset = ram_size + vga_ram_size;
vga_bios_offset = bios_offset + 256 * 1024;
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
bios_size = get_image_size(buf);
if (bios_size <= 0 ||
(bios_size % 65536) != 0 ||
bios_size > (256 * 1024)) {
goto bios_error;
}
ret = load_image(buf, phys_ram_base + bios_offset);
if (ret != bios_size) {
bios_error:
fprintf(stderr, "qemu: could not load PC bios '%s'\n", buf);
exit(1);
}
/* VGA BIOS load */
if (cirrus_vga_enabled) {
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
} else {
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
}
ret = load_image(buf, phys_ram_base + vga_bios_offset);
/* setup basic memory access */
cpu_register_physical_memory(0xc0000, 0x10000,
vga_bios_offset | IO_MEM_ROM);
/* map the last 128KB of the BIOS in ISA space */
isa_bios_size = bios_size;
if (isa_bios_size > (128 * 1024))
isa_bios_size = 128 * 1024;
cpu_register_physical_memory(0xd0000, (192 * 1024) - isa_bios_size,
IO_MEM_UNASSIGNED);
cpu_register_physical_memory(0x100000 - isa_bios_size,
isa_bios_size,
(bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
/* map all the bios at the top of memory */
cpu_register_physical_memory((uint32_t)(-bios_size),
bios_size, bios_offset | IO_MEM_ROM);
bochs_bios_init();
if (linux_boot) {
uint8_t bootsect[512];
uint8_t old_bootsect[512];
if (bs_table[0] == NULL) {
fprintf(stderr, "A disk image must be given for 'hda' when booting a Linux kernel\n");
exit(1);
}
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, LINUX_BOOT_FILENAME);
ret = load_image(buf, bootsect);
if (ret != sizeof(bootsect)) {
fprintf(stderr, "qemu: could not load linux boot sector '%s'\n",
buf);
exit(1);
}
if (bdrv_read(bs_table[0], 0, old_bootsect, 1) >= 0) {
/* copy the MSDOS partition table */
memcpy(bootsect + 0x1be, old_bootsect + 0x1be, 0x40);
}
bdrv_set_boot_sector(bs_table[0], bootsect, sizeof(bootsect));
/* now we can load the kernel */
ret = load_kernel(kernel_filename,
phys_ram_base + KERNEL_LOAD_ADDR,
phys_ram_base + KERNEL_PARAMS_ADDR);
if (ret < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
/* load initrd */
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 initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
}
if (initrd_size > 0) {
stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, INITRD_LOAD_ADDR);
stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x21c, initrd_size);
}
pstrcpy(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096,
kernel_cmdline);
stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x20, 0xA33F);
stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x22,
KERNEL_CMDLINE_ADDR - KERNEL_PARAMS_ADDR);
/* loader type */
stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01);
}
if (pci_enabled) {
pci_bus = i440fx_init();
piix3_init(pci_bus);
} else {
pci_bus = NULL;
}
/* init basic PC hardware */
register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
if (cirrus_vga_enabled) {
if (pci_enabled) {
pci_cirrus_vga_init(pci_bus,
ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
} else {
isa_cirrus_vga_init(ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
}
} else {
vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
}
rtc_state = rtc_init(0x70, 8);
register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
pic_init();
pit = pit_init(0x40, 0);
fd = serial_open_device();
serial_init(0x3f8, 4, fd);
if (pci_enabled) {
for(i = 0; i < nb_nics; i++) {
pci_ne2000_init(pci_bus, &nd_table[i]);
}
pci_piix3_ide_init(pci_bus, bs_table);
} else {
nb_nics1 = nb_nics;
if (nb_nics1 > NE2000_NB_MAX)
nb_nics1 = NE2000_NB_MAX;
for(i = 0; i < nb_nics1; i++) {
isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]);
}
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]);
}
}
kbd_init();
DMA_init(0);
#ifndef _WIN32
if (audio_enabled) {
/* no audio supported yet for win32 */
AUD_init();
SB16_init();
}
#endif
floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
cmos_init(ram_size, boot_device);
/* must be done after all PCI devices are instanciated */
/* XXX: should be done in the Bochs BIOS */
if (pci_enabled) {
pci_bios_init();
}
}

1504
hw/pci.c Normal file

File diff suppressed because it is too large Load Diff

706
hw/pckbd.c Normal file
View File

@@ -0,0 +1,706 @@
/*
* QEMU PC keyboard emulation
*
* Copyright (c) 2003 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 PC keyboard */
//#define DEBUG_KBD
/* debug PC keyboard : only mouse */
//#define DEBUG_MOUSE
/* Keyboard Controller Commands */
#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */
#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */
#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */
#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */
#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */
#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */
#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */
#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */
#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */
#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */
#define KBD_CCMD_READ_INPORT 0xC0 /* read input port */
#define KBD_CCMD_READ_OUTPORT 0xD0 /* read output port */
#define KBD_CCMD_WRITE_OUTPORT 0xD1 /* write output port */
#define KBD_CCMD_WRITE_OBUF 0xD2
#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if
initiated by the auxiliary device */
#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */
#define KBD_CCMD_DISABLE_A20 0xDD /* HP vectra only ? */
#define KBD_CCMD_ENABLE_A20 0xDF /* HP vectra only ? */
#define KBD_CCMD_RESET 0xFE
/* Keyboard Commands */
#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
#define KBD_CMD_ECHO 0xEE
#define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
#define KBD_CMD_RESET 0xFF /* Reset */
/* Keyboard Replies */
#define KBD_REPLY_POR 0xAA /* Power on reset */
#define KBD_REPLY_ACK 0xFA /* Command ACK */
#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
/* Status Register Bits */
#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
#define KBD_STAT_SELFTEST 0x04 /* Self test successful */
#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */
#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */
#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */
#define KBD_STAT_PERR 0x80 /* Parity error */
/* Controller Mode Register Bits */
#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */
#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */
#define KBD_MODE_SYS 0x04 /* The system flag (?) */
#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */
#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */
#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */
#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */
#define KBD_MODE_RFU 0x80
/* Mouse Commands */
#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
#define AUX_SET_RES 0xE8 /* Set resolution */
#define AUX_GET_SCALE 0xE9 /* Get scaling factor */
#define AUX_SET_STREAM 0xEA /* Set stream mode */
#define AUX_POLL 0xEB /* Poll */
#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
#define AUX_SET_WRAP 0xEE /* Set wrap mode */
#define AUX_SET_REMOTE 0xF0 /* Set remote mode */
#define AUX_GET_TYPE 0xF2 /* Get type */
#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
#define AUX_SET_DEFAULT 0xF6
#define AUX_RESET 0xFF /* Reset aux device */
#define AUX_ACK 0xFA /* Command byte ACK. */
#define MOUSE_STATUS_REMOTE 0x40
#define MOUSE_STATUS_ENABLED 0x20
#define MOUSE_STATUS_SCALE21 0x10
#define KBD_QUEUE_SIZE 256
typedef struct {
uint8_t aux[KBD_QUEUE_SIZE];
uint8_t data[KBD_QUEUE_SIZE];
int rptr, wptr, count;
} KBDQueue;
typedef struct KBDState {
KBDQueue queue;
uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
uint8_t status;
uint8_t mode;
/* keyboard state */
int kbd_write_cmd;
int scan_enabled;
/* mouse state */
int mouse_write_cmd;
uint8_t mouse_status;
uint8_t mouse_resolution;
uint8_t mouse_sample_rate;
uint8_t mouse_wrap;
uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
uint8_t mouse_detect_state;
int mouse_dx; /* current values, needed for 'poll' mode */
int mouse_dy;
int mouse_dz;
uint8_t mouse_buttons;
} KBDState;
KBDState kbd_state;
/* update irq and KBD_STAT_[MOUSE_]OBF */
/* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be
incorrect, but it avoids having to simulate exact delays */
static void kbd_update_irq(KBDState *s)
{
KBDQueue *q = &s->queue;
int irq12_level, irq1_level;
irq1_level = 0;
irq12_level = 0;
s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
if (q->count != 0) {
s->status |= KBD_STAT_OBF;
if (q->aux[q->rptr]) {
s->status |= KBD_STAT_MOUSE_OBF;
if (s->mode & KBD_MODE_MOUSE_INT)
irq12_level = 1;
} else {
if ((s->mode & KBD_MODE_KBD_INT) &&
!(s->mode & KBD_MODE_DISABLE_KBD))
irq1_level = 1;
}
}
pic_set_irq(1, irq1_level);
pic_set_irq(12, irq12_level);
}
static void kbd_queue(KBDState *s, int b, int aux)
{
KBDQueue *q = &s->queue;
#if defined(DEBUG_MOUSE) || defined(DEBUG_KBD)
if (aux)
printf("mouse event: 0x%02x\n", b);
#ifdef DEBUG_KBD
else
printf("kbd event: 0x%02x\n", b);
#endif
#endif
if (q->count >= KBD_QUEUE_SIZE)
return;
q->aux[q->wptr] = aux;
q->data[q->wptr] = b;
if (++q->wptr == KBD_QUEUE_SIZE)
q->wptr = 0;
q->count++;
kbd_update_irq(s);
}
static void pc_kbd_put_keycode(void *opaque, int keycode)
{
KBDState *s = opaque;
kbd_queue(s, keycode, 0);
}
static uint32_t kbd_read_status(void *opaque, uint32_t addr)
{
KBDState *s = opaque;
int val;
val = s->status;
#if defined(DEBUG_KBD)
printf("kbd: read status=0x%02x\n", val);
#endif
return val;
}
static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val)
{
KBDState *s = opaque;
#ifdef DEBUG_KBD
printf("kbd: write cmd=0x%02x\n", val);
#endif
switch(val) {
case KBD_CCMD_READ_MODE:
kbd_queue(s, s->mode, 0);
break;
case KBD_CCMD_WRITE_MODE:
case KBD_CCMD_WRITE_OBUF:
case KBD_CCMD_WRITE_AUX_OBUF:
case KBD_CCMD_WRITE_MOUSE:
case KBD_CCMD_WRITE_OUTPORT:
s->write_cmd = val;
break;
case KBD_CCMD_MOUSE_DISABLE:
s->mode |= KBD_MODE_DISABLE_MOUSE;
break;
case KBD_CCMD_MOUSE_ENABLE:
s->mode &= ~KBD_MODE_DISABLE_MOUSE;
break;
case KBD_CCMD_TEST_MOUSE:
kbd_queue(s, 0x00, 0);
break;
case KBD_CCMD_SELF_TEST:
s->status |= KBD_STAT_SELFTEST;
kbd_queue(s, 0x55, 0);
break;
case KBD_CCMD_KBD_TEST:
kbd_queue(s, 0x00, 0);
break;
case KBD_CCMD_KBD_DISABLE:
s->mode |= KBD_MODE_DISABLE_KBD;
kbd_update_irq(s);
break;
case KBD_CCMD_KBD_ENABLE:
s->mode &= ~KBD_MODE_DISABLE_KBD;
kbd_update_irq(s);
break;
case KBD_CCMD_READ_INPORT:
kbd_queue(s, 0x00, 0);
break;
case KBD_CCMD_READ_OUTPORT:
/* XXX: check that */
#ifdef TARGET_I386
val = 0x01 | (((cpu_single_env->a20_mask >> 20) & 1) << 1);
#else
val = 0x01;
#endif
if (s->status & KBD_STAT_OBF)
val |= 0x10;
if (s->status & KBD_STAT_MOUSE_OBF)
val |= 0x20;
kbd_queue(s, val, 0);
break;
#ifdef TARGET_I386
case KBD_CCMD_ENABLE_A20:
cpu_x86_set_a20(cpu_single_env, 1);
break;
case KBD_CCMD_DISABLE_A20:
cpu_x86_set_a20(cpu_single_env, 0);
break;
#endif
case KBD_CCMD_RESET:
qemu_system_reset_request();
break;
case 0xff:
/* ignore that - I don't know what is its use */
break;
default:
fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", val);
break;
}
}
static uint32_t kbd_read_data(void *opaque, uint32_t addr)
{
KBDState *s = opaque;
KBDQueue *q;
int val, index, aux;
q = &s->queue;
if (q->count == 0) {
/* NOTE: if no data left, we return the last keyboard one
(needed for EMM386) */
/* XXX: need a timer to do things correctly */
index = q->rptr - 1;
if (index < 0)
index = KBD_QUEUE_SIZE - 1;
val = q->data[index];
} else {
aux = q->aux[q->rptr];
val = q->data[q->rptr];
if (++q->rptr == KBD_QUEUE_SIZE)
q->rptr = 0;
q->count--;
/* reading deasserts IRQ */
if (aux)
pic_set_irq(12, 0);
else
pic_set_irq(1, 0);
}
/* reassert IRQs if data left */
kbd_update_irq(s);
#ifdef DEBUG_KBD
printf("kbd: read data=0x%02x\n", val);
#endif
return val;
}
static void kbd_reset_keyboard(KBDState *s)
{
s->scan_enabled = 1;
}
static void kbd_write_keyboard(KBDState *s, int val)
{
switch(s->kbd_write_cmd) {
default:
case -1:
switch(val) {
case 0x00:
kbd_queue(s, KBD_REPLY_ACK, 0);
break;
case 0x05:
kbd_queue(s, KBD_REPLY_RESEND, 0);
break;
case KBD_CMD_GET_ID:
kbd_queue(s, KBD_REPLY_ACK, 0);
kbd_queue(s, 0xab, 0);
kbd_queue(s, 0x83, 0);
break;
case KBD_CMD_ECHO:
kbd_queue(s, KBD_CMD_ECHO, 0);
break;
case KBD_CMD_ENABLE:
s->scan_enabled = 1;
kbd_queue(s, KBD_REPLY_ACK, 0);
break;
case KBD_CMD_SET_LEDS:
case KBD_CMD_SET_RATE:
s->kbd_write_cmd = val;
kbd_queue(s, KBD_REPLY_ACK, 0);
break;
case KBD_CMD_RESET_DISABLE:
kbd_reset_keyboard(s);
s->scan_enabled = 0;
kbd_queue(s, KBD_REPLY_ACK, 0);
break;
case KBD_CMD_RESET_ENABLE:
kbd_reset_keyboard(s);
s->scan_enabled = 1;
kbd_queue(s, KBD_REPLY_ACK, 0);
break;
case KBD_CMD_RESET:
kbd_reset_keyboard(s);
kbd_queue(s, KBD_REPLY_ACK, 0);
kbd_queue(s, KBD_REPLY_POR, 0);
break;
default:
kbd_queue(s, KBD_REPLY_ACK, 0);
break;
}
break;
case KBD_CMD_SET_LEDS:
kbd_queue(s, KBD_REPLY_ACK, 0);
s->kbd_write_cmd = -1;
break;
case KBD_CMD_SET_RATE:
kbd_queue(s, KBD_REPLY_ACK, 0);
s->kbd_write_cmd = -1;
break;
}
}
static void kbd_mouse_send_packet(KBDState *s)
{
unsigned int b;
int dx1, dy1, dz1;
dx1 = s->mouse_dx;
dy1 = s->mouse_dy;
dz1 = s->mouse_dz;
/* XXX: increase range to 8 bits ? */
if (dx1 > 127)
dx1 = 127;
else if (dx1 < -127)
dx1 = -127;
if (dy1 > 127)
dy1 = 127;
else if (dy1 < -127)
dy1 = -127;
b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
kbd_queue(s, b, 1);
kbd_queue(s, dx1 & 0xff, 1);
kbd_queue(s, dy1 & 0xff, 1);
/* extra byte for IMPS/2 or IMEX */
switch(s->mouse_type) {
default:
break;
case 3:
if (dz1 > 127)
dz1 = 127;
else if (dz1 < -127)
dz1 = -127;
kbd_queue(s, dz1 & 0xff, 1);
break;
case 4:
if (dz1 > 7)
dz1 = 7;
else if (dz1 < -7)
dz1 = -7;
b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
kbd_queue(s, b, 1);
break;
}
/* update deltas */
s->mouse_dx -= dx1;
s->mouse_dy -= dy1;
s->mouse_dz -= dz1;
}
static void pc_kbd_mouse_event(void *opaque,
int dx, int dy, int dz, int buttons_state)
{
KBDState *s = opaque;
/* check if deltas are recorded when disabled */
if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
return;
s->mouse_dx += dx;
s->mouse_dy -= dy;
s->mouse_dz += dz;
/* XXX: SDL sometimes generates nul events: we delete them */
if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
s->mouse_buttons == buttons_state)
return;
s->mouse_buttons = buttons_state;
if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
(s->queue.count < (KBD_QUEUE_SIZE - 16))) {
for(;;) {
/* if not remote, send event. Multiple events are sent if
too big deltas */
kbd_mouse_send_packet(s);
if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
break;
}
}
}
static void kbd_write_mouse(KBDState *s, int val)
{
#ifdef DEBUG_MOUSE
printf("kbd: write mouse 0x%02x\n", val);
#endif
switch(s->mouse_write_cmd) {
default:
case -1:
/* mouse command */
if (s->mouse_wrap) {
if (val == AUX_RESET_WRAP) {
s->mouse_wrap = 0;
kbd_queue(s, AUX_ACK, 1);
return;
} else if (val != AUX_RESET) {
kbd_queue(s, val, 1);
return;
}
}
switch(val) {
case AUX_SET_SCALE11:
s->mouse_status &= ~MOUSE_STATUS_SCALE21;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_SCALE21:
s->mouse_status |= MOUSE_STATUS_SCALE21;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_STREAM:
s->mouse_status &= ~MOUSE_STATUS_REMOTE;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_WRAP:
s->mouse_wrap = 1;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_REMOTE:
s->mouse_status |= MOUSE_STATUS_REMOTE;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_GET_TYPE:
kbd_queue(s, AUX_ACK, 1);
kbd_queue(s, s->mouse_type, 1);
break;
case AUX_SET_RES:
case AUX_SET_SAMPLE:
s->mouse_write_cmd = val;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_GET_SCALE:
kbd_queue(s, AUX_ACK, 1);
kbd_queue(s, s->mouse_status, 1);
kbd_queue(s, s->mouse_resolution, 1);
kbd_queue(s, s->mouse_sample_rate, 1);
break;
case AUX_POLL:
kbd_queue(s, AUX_ACK, 1);
kbd_mouse_send_packet(s);
break;
case AUX_ENABLE_DEV:
s->mouse_status |= MOUSE_STATUS_ENABLED;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_DISABLE_DEV:
s->mouse_status &= ~MOUSE_STATUS_ENABLED;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_SET_DEFAULT:
s->mouse_sample_rate = 100;
s->mouse_resolution = 2;
s->mouse_status = 0;
kbd_queue(s, AUX_ACK, 1);
break;
case AUX_RESET:
s->mouse_sample_rate = 100;
s->mouse_resolution = 2;
s->mouse_status = 0;
kbd_queue(s, AUX_ACK, 1);
kbd_queue(s, 0xaa, 1);
kbd_queue(s, s->mouse_type, 1);
break;
default:
break;
}
break;
case AUX_SET_SAMPLE:
s->mouse_sample_rate = val;
#if 0
/* detect IMPS/2 or IMEX */
switch(s->mouse_detect_state) {
default:
case 0:
if (val == 200)
s->mouse_detect_state = 1;
break;
case 1:
if (val == 100)
s->mouse_detect_state = 2;
else if (val == 200)
s->mouse_detect_state = 3;
else
s->mouse_detect_state = 0;
break;
case 2:
if (val == 80)
s->mouse_type = 3; /* IMPS/2 */
s->mouse_detect_state = 0;
break;
case 3:
if (val == 80)
s->mouse_type = 4; /* IMEX */
s->mouse_detect_state = 0;
break;
}
#endif
kbd_queue(s, AUX_ACK, 1);
s->mouse_write_cmd = -1;
break;
case AUX_SET_RES:
s->mouse_resolution = val;
kbd_queue(s, AUX_ACK, 1);
s->mouse_write_cmd = -1;
break;
}
}
void kbd_write_data(void *opaque, uint32_t addr, uint32_t val)
{
KBDState *s = opaque;
#ifdef DEBUG_KBD
printf("kbd: write data=0x%02x\n", val);
#endif
switch(s->write_cmd) {
case 0:
kbd_write_keyboard(s, val);
break;
case KBD_CCMD_WRITE_MODE:
s->mode = val;
kbd_update_irq(s);
break;
case KBD_CCMD_WRITE_OBUF:
kbd_queue(s, val, 0);
break;
case KBD_CCMD_WRITE_AUX_OBUF:
kbd_queue(s, val, 1);
break;
case KBD_CCMD_WRITE_OUTPORT:
#ifdef TARGET_I386
cpu_x86_set_a20(cpu_single_env, (val >> 1) & 1);
#endif
if (!(val & 1)) {
qemu_system_reset_request();
}
break;
case KBD_CCMD_WRITE_MOUSE:
kbd_write_mouse(s, val);
break;
default:
break;
}
s->write_cmd = 0;
}
static void kbd_reset(void *opaque)
{
KBDState *s = opaque;
KBDQueue *q;
s->kbd_write_cmd = -1;
s->mouse_write_cmd = -1;
s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT;
s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;
q = &s->queue;
q->rptr = 0;
q->wptr = 0;
q->count = 0;
}
static void kbd_save(QEMUFile* f, void* opaque)
{
KBDState *s = (KBDState*)opaque;
qemu_put_8s(f, &s->write_cmd);
qemu_put_8s(f, &s->status);
qemu_put_8s(f, &s->mode);
qemu_put_be32s(f, &s->kbd_write_cmd);
qemu_put_be32s(f, &s->scan_enabled);
qemu_put_be32s(f, &s->mouse_write_cmd);
qemu_put_8s(f, &s->mouse_status);
qemu_put_8s(f, &s->mouse_resolution);
qemu_put_8s(f, &s->mouse_sample_rate);
qemu_put_8s(f, &s->mouse_wrap);
qemu_put_8s(f, &s->mouse_type);
qemu_put_8s(f, &s->mouse_detect_state);
qemu_put_be32s(f, &s->mouse_dx);
qemu_put_be32s(f, &s->mouse_dy);
qemu_put_be32s(f, &s->mouse_dz);
qemu_put_8s(f, &s->mouse_buttons);
}
static int kbd_load(QEMUFile* f, void* opaque, int version_id)
{
KBDState *s = (KBDState*)opaque;
if (version_id != 1)
return -EINVAL;
qemu_get_8s(f, &s->write_cmd);
qemu_get_8s(f, &s->status);
qemu_get_8s(f, &s->mode);
qemu_get_be32s(f, &s->kbd_write_cmd);
qemu_get_be32s(f, &s->scan_enabled);
qemu_get_be32s(f, &s->mouse_write_cmd);
qemu_get_8s(f, &s->mouse_status);
qemu_get_8s(f, &s->mouse_resolution);
qemu_get_8s(f, &s->mouse_sample_rate);
qemu_get_8s(f, &s->mouse_wrap);
qemu_get_8s(f, &s->mouse_type);
qemu_get_8s(f, &s->mouse_detect_state);
qemu_get_be32s(f, &s->mouse_dx);
qemu_get_be32s(f, &s->mouse_dy);
qemu_get_be32s(f, &s->mouse_dz);
qemu_get_8s(f, &s->mouse_buttons);
return 0;
}
void kbd_init(void)
{
KBDState *s = &kbd_state;
kbd_reset(s);
register_savevm("pckbd", 0, 1, kbd_save, kbd_load, s);
register_ioport_read(0x60, 1, 1, kbd_read_data, s);
register_ioport_write(0x60, 1, 1, kbd_write_data, s);
register_ioport_read(0x64, 1, 1, kbd_read_status, s);
register_ioport_write(0x64, 1, 1, kbd_write_command, s);
qemu_add_kbd_event_handler(pc_kbd_put_keycode, s);
qemu_add_mouse_event_handler(pc_kbd_mouse_event, s);
qemu_register_reset(kbd_reset, s);
}

462
hw/ppc.c Normal file
View File

@@ -0,0 +1,462 @@
/*
* QEMU generic PPC hardware System Emulator
*
* Copyright (c) 2003-2004 Jocelyn Mayer
*
* 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"
#include "m48t59.h"
/*****************************************************************************/
/* PPC time base and decrementer emulation */
//#define DEBUG_TB
struct ppc_tb_t {
/* Time base management */
int64_t tb_offset; /* Compensation */
uint32_t tb_freq; /* TB frequency */
/* Decrementer management */
uint64_t decr_next; /* Tick for next decr interrupt */
struct QEMUTimer *decr_timer;
};
static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env)
{
/* TB time in tb periods */
return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset,
tb_env->tb_freq, ticks_per_sec);
}
uint32_t cpu_ppc_load_tbl (CPUState *env)
{
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
tb = cpu_ppc_get_tb(tb_env);
#ifdef DEBUG_TB
{
static int last_time;
int now;
now = time(NULL);
if (last_time != now) {
last_time = now;
printf("%s: tb=0x%016lx %d %08lx\n",
__func__, tb, now, tb_env->tb_offset);
}
}
#endif
return tb & 0xFFFFFFFF;
}
uint32_t cpu_ppc_load_tbu (CPUState *env)
{
ppc_tb_t *tb_env = env->tb_env;
uint64_t tb;
tb = cpu_ppc_get_tb(tb_env);
#ifdef DEBUG_TB
printf("%s: tb=0x%016lx\n", __func__, tb);
#endif
return tb >> 32;
}
static void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t value)
{
tb_env->tb_offset = muldiv64(value, ticks_per_sec, tb_env->tb_freq)
- qemu_get_clock(vm_clock);
#ifdef DEBUG_TB
printf("%s: tb=0x%016lx offset=%08x\n", __func__, value);
#endif
}
void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
{
ppc_tb_t *tb_env = env->tb_env;
cpu_ppc_store_tb(tb_env,
((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
}
void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
{
ppc_tb_t *tb_env = env->tb_env;
cpu_ppc_store_tb(tb_env,
((uint64_t)cpu_ppc_load_tbu(env) << 32) | value);
}
uint32_t cpu_ppc_load_decr (CPUState *env)
{
ppc_tb_t *tb_env = env->tb_env;
uint32_t decr;
decr = muldiv64(tb_env->decr_next - qemu_get_clock(vm_clock),
tb_env->tb_freq, ticks_per_sec);
#if defined(DEBUG_TB)
printf("%s: 0x%08x\n", __func__, decr);
#endif
return decr;
}
/* When decrementer expires,
* all we need to do is generate or queue a CPU exception
*/
static inline void cpu_ppc_decr_excp (CPUState *env)
{
/* Raise it */
#ifdef DEBUG_TB
printf("raise decrementer exception\n");
#endif
cpu_interrupt(env, CPU_INTERRUPT_TIMER);
}
static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
uint32_t value, int is_excp)
{
ppc_tb_t *tb_env = env->tb_env;
uint64_t now, next;
#ifdef DEBUG_TB
printf("%s: 0x%08x => 0x%08x\n", __func__, decr, value);
#endif
now = qemu_get_clock(vm_clock);
next = now + muldiv64(value, ticks_per_sec, tb_env->tb_freq);
if (is_excp)
next += tb_env->decr_next - now;
if (next == now)
next++;
tb_env->decr_next = next;
/* Adjust timer */
qemu_mod_timer(tb_env->decr_timer, next);
/* If we set a negative value and the decrementer was positive,
* raise an exception.
*/
if ((value & 0x80000000) && !(decr & 0x80000000))
cpu_ppc_decr_excp(env);
}
void cpu_ppc_store_decr (CPUState *env, uint32_t value)
{
_cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
}
static void cpu_ppc_decr_cb (void *opaque)
{
_cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
}
/* Set up (once) timebase frequency (in Hz) */
ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq)
{
ppc_tb_t *tb_env;
tb_env = qemu_mallocz(sizeof(ppc_tb_t));
if (tb_env == NULL)
return NULL;
env->tb_env = tb_env;
if (tb_env->tb_freq == 0 || 1) {
tb_env->tb_freq = freq;
/* Create new timer */
tb_env->decr_timer =
qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
/* There is a bug in 2.4 kernels:
* if a decrementer exception is pending when it enables msr_ee,
* it's not ready to handle it...
*/
_cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
}
return tb_env;
}
#if 0
/*****************************************************************************/
/* Handle system reset (for now, just stop emulation) */
void cpu_ppc_reset (CPUState *env)
{
printf("Reset asked... Stop emulation\n");
abort();
}
#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)
{
addr &= 0xF;
switch (addr) {
case 0:
printf("%c", val);
break;
case 1:
printf("\n");
fflush(stdout);
break;
case 2:
printf("Set loglevel to %04x\n", val);
cpu_set_log(val | 0x100);
break;
}
}
/*****************************************************************************/
/* NVRAM helpers */
void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
{
m48t59_set_addr(nvram, addr);
m48t59_write(nvram, value);
}
uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
{
m48t59_set_addr(nvram, addr);
return m48t59_read(nvram);
}
void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
{
m48t59_set_addr(nvram, addr);
m48t59_write(nvram, value >> 8);
m48t59_set_addr(nvram, addr + 1);
m48t59_write(nvram, value & 0xFF);
}
uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
{
uint16_t tmp;
m48t59_set_addr(nvram, addr);
tmp = m48t59_read(nvram) << 8;
m48t59_set_addr(nvram, addr + 1);
tmp |= m48t59_read(nvram);
return tmp;
}
void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
{
m48t59_set_addr(nvram, addr);
m48t59_write(nvram, value >> 24);
m48t59_set_addr(nvram, addr + 1);
m48t59_write(nvram, (value >> 16) & 0xFF);
m48t59_set_addr(nvram, addr + 2);
m48t59_write(nvram, (value >> 8) & 0xFF);
m48t59_set_addr(nvram, addr + 3);
m48t59_write(nvram, value & 0xFF);
}
uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
{
uint32_t tmp;
m48t59_set_addr(nvram, addr);
tmp = m48t59_read(nvram) << 24;
m48t59_set_addr(nvram, addr + 1);
tmp |= m48t59_read(nvram) << 16;
m48t59_set_addr(nvram, addr + 2);
tmp |= m48t59_read(nvram) << 8;
m48t59_set_addr(nvram, addr + 3);
tmp |= m48t59_read(nvram);
return tmp;
}
void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
const unsigned char *str, uint32_t max)
{
int i;
for (i = 0; i < max && str[i] != '\0'; i++) {
m48t59_set_addr(nvram, addr + i);
m48t59_write(nvram, str[i]);
}
m48t59_set_addr(nvram, addr + max - 1);
m48t59_write(nvram, '\0');
}
int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
{
int i;
memset(dst, 0, max);
for (i = 0; i < max; i++) {
dst[i] = NVRAM_get_byte(nvram, addr + i);
if (dst[i] == '\0')
break;
}
return i;
}
static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
{
uint16_t tmp;
uint16_t pd, pd1, pd2;
tmp = prev >> 8;
pd = prev ^ value;
pd1 = pd & 0x000F;
pd2 = ((pd >> 4) & 0x000F) ^ pd1;
tmp ^= (pd1 << 3) | (pd1 << 8);
tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
return tmp;
}
uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
{
uint32_t i;
uint16_t crc = 0xFFFF;
int odd;
odd = count & 1;
count &= ~1;
for (i = 0; i != count; i++) {
crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
}
if (odd) {
crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
}
return crc;
}
#define CMDLINE_ADDR 0x017ff000
int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
const unsigned char *arch,
uint32_t RAM_size, int boot_device,
uint32_t kernel_image, uint32_t kernel_size,
const char *cmdline,
uint32_t initrd_image, uint32_t initrd_size,
uint32_t NVRAM_image,
int width, int height, int depth)
{
uint16_t crc;
/* Set parameters for Open Hack'Ware BIOS */
NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */
NVRAM_set_word(nvram, 0x14, NVRAM_size);
NVRAM_set_string(nvram, 0x20, arch, 16);
NVRAM_set_lword(nvram, 0x30, RAM_size);
NVRAM_set_byte(nvram, 0x34, boot_device);
NVRAM_set_lword(nvram, 0x38, kernel_image);
NVRAM_set_lword(nvram, 0x3C, kernel_size);
if (cmdline) {
/* XXX: put the cmdline in NVRAM too ? */
strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR);
NVRAM_set_lword(nvram, 0x44, strlen(cmdline));
} else {
NVRAM_set_lword(nvram, 0x40, 0);
NVRAM_set_lword(nvram, 0x44, 0);
}
NVRAM_set_lword(nvram, 0x48, initrd_image);
NVRAM_set_lword(nvram, 0x4C, initrd_size);
NVRAM_set_lword(nvram, 0x50, NVRAM_image);
NVRAM_set_word(nvram, 0x54, width);
NVRAM_set_word(nvram, 0x56, height);
NVRAM_set_word(nvram, 0x58, depth);
crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
NVRAM_set_word(nvram, 0xFC, crc);
return 0;
}
/*****************************************************************************/
void ppc_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)
{
if (prep_enabled) {
ppc_prep_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
snapshot, kernel_filename, kernel_cmdline,
initrd_filename);
} else {
ppc_chrp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
snapshot, kernel_filename, kernel_cmdline,
initrd_filename);
}
/* Special port to get debug messages from Open-Firmware */
register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
}

234
hw/ppc_chrp.c Normal file
View File

@@ -0,0 +1,234 @@
/*
* QEMU PPC CHRP/PMAC hardware System Emulator
*
* Copyright (c) 2004 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"
#define BIOS_FILENAME "ppc_rom.bin"
#define NVRAM_SIZE 0x2000
#define KERNEL_LOAD_ADDR 0x01000000
#define INITRD_LOAD_ADDR 0x01800000
/* MacIO devices (mapped inside the MacIO address space): CUDA, DBDMA,
NVRAM (not implemented). */
static int dbdma_mem_index;
static int cuda_mem_index;
static int ide0_mem_index;
static int ide1_mem_index;
static int openpic_mem_index;
/* DBDMA: currently no op - should suffice right now */
static void dbdma_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
printf("%s: 0x%08x <= 0x%08x\n", __func__, addr, value);
}
static void dbdma_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
}
static void dbdma_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
}
static uint32_t dbdma_readb (void *opaque, target_phys_addr_t addr)
{
printf("%s: 0x%08x => 0x00000000\n", __func__, addr);
return 0;
}
static uint32_t dbdma_readw (void *opaque, target_phys_addr_t addr)
{
return 0;
}
static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
{
return 0;
}
static CPUWriteMemoryFunc *dbdma_write[] = {
&dbdma_writeb,
&dbdma_writew,
&dbdma_writel,
};
static CPUReadMemoryFunc *dbdma_read[] = {
&dbdma_readb,
&dbdma_readw,
&dbdma_readl,
};
static void macio_map(PCIDevice *pci_dev, int region_num,
uint32_t addr, uint32_t size, int type)
{
cpu_register_physical_memory(addr + 0x08000, 0x1000, dbdma_mem_index);
cpu_register_physical_memory(addr + 0x16000, 0x2000, cuda_mem_index);
cpu_register_physical_memory(addr + 0x1f000, 0x1000, ide0_mem_index);
cpu_register_physical_memory(addr + 0x20000, 0x1000, ide1_mem_index);
cpu_register_physical_memory(addr + 0x40000, 0x40000, openpic_mem_index);
}
static void macio_init(PCIBus *bus)
{
PCIDevice *d;
d = pci_register_device(bus, "macio", sizeof(PCIDevice),
-1, NULL, NULL);
/* Note: this code is strongly inspirated from the corresponding code
in PearPC */
d->config[0x00] = 0x6b; // vendor_id
d->config[0x01] = 0x10;
d->config[0x02] = 0x22;
d->config[0x03] = 0x00;
d->config[0x0a] = 0x00; // class_sub = pci2pci
d->config[0x0b] = 0xff; // class_base = bridge
d->config[0x0e] = 0x00; // header_type
d->config[0x3d] = 0x01; // interrupt on pin 1
dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL);
pci_register_io_region(d, 0, 0x80000,
PCI_ADDRESS_SPACE_MEM, macio_map);
}
/* PowerPC PREP hardware initialisation */
void ppc_chrp_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];
openpic_t *openpic;
m48t59_t *nvram;
int PPC_io_memory;
int ret, linux_boot, i, fd;
unsigned long bios_offset;
uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
PCIBus *pci_bus;
linux_boot = (kernel_filename != NULL);
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
/* allocate and load BIOS */
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) {
fprintf(stderr, "qemu: could not load PPC PREP bios '%s'\n", buf);
exit(1);
}
cpu_register_physical_memory((uint32_t)(-BIOS_SIZE),
BIOS_SIZE, bios_offset | IO_MEM_ROM);
cpu_single_env->nip = 0xfffffffc;
if (linux_boot) {
kernel_base = KERNEL_LOAD_ADDR;
/* now we can load the kernel */
kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
/* load initrd */
if (initrd_filename) {
initrd_base = INITRD_LOAD_ADDR;
initrd_size = load_image(initrd_filename,
phys_ram_base + initrd_base);
if (initrd_size < 0) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
} else {
initrd_base = 0;
initrd_size = 0;
}
boot_device = 'm';
} else {
kernel_base = 0;
kernel_size = 0;
initrd_base = 0;
initrd_size = 0;
}
/* Register CPU as a 74x/75x */
cpu_ppc_register(cpu_single_env, 0x00080000);
/* Set time-base frequency to 100 Mhz */
cpu_ppc_tb_init(cpu_single_env, 100UL * 1000UL * 1000UL);
isa_mem_base = 0x80000000;
pci_bus = pci_pmac_init();
/* 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);
/* init basic PC hardware */
vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
openpic = openpic_init(NULL, &openpic_mem_index, 1);
pci_pmac_set_openpic(pci_bus, openpic);
/* XXX: suppress that */
pic_init();
/* XXX: use Mac Serial port */
fd = serial_open_device();
serial_init(0x3f8, 4, fd);
for(i = 0; i < nb_nics; i++) {
pci_ne2000_init(pci_bus, &nd_table[i]);
}
ide0_mem_index = pmac_ide_init(&bs_table[0], openpic, 0x13);
ide1_mem_index = pmac_ide_init(&bs_table[2], openpic, 0x13);
/* cuda also initialize ADB */
cuda_mem_index = cuda_init(openpic, 0x19);
adb_kbd_init(&adb_bus);
adb_mouse_init(&adb_bus);
macio_init(pci_bus);
nvram = m48t59_init(8, 0xFFF04000, 0x0074, NVRAM_SIZE);
if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
graphic_depth = 15;
PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "CHRP", ram_size, boot_device,
kernel_base, kernel_size,
kernel_cmdline,
initrd_base, initrd_size,
/* XXX: need an option to load a NVRAM image */
0,
graphic_width, graphic_height, graphic_depth);
/* No PCI init: the BIOS will do it */
}

549
hw/ppc_prep.c Normal file
View File

@@ -0,0 +1,549 @@
/*
* QEMU PPC PREP hardware System Emulator
*
* Copyright (c) 2003-2004 Jocelyn Mayer
*
* 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"
//#define HARD_DEBUG_PPC_IO
//#define DEBUG_PPC_IO
#define BIOS_FILENAME "ppc_rom.bin"
#define KERNEL_LOAD_ADDR 0x01000000
#define INITRD_LOAD_ADDR 0x01800000
extern int loglevel;
extern FILE *logfile;
#if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO)
#define DEBUG_PPC_IO
#endif
#if defined (HARD_DEBUG_PPC_IO)
#define PPC_IO_DPRINTF(fmt, args...) \
do { \
if (loglevel & CPU_LOG_IOPORT) { \
fprintf(logfile, "%s: " fmt, __func__ , ##args); \
} else { \
printf("%s : " fmt, __func__ , ##args); \
} \
} while (0)
#elif defined (DEBUG_PPC_IO)
#define PPC_IO_DPRINTF(fmt, args...) \
do { \
if (loglevel & CPU_LOG_IOPORT) { \
fprintf(logfile, "%s: " fmt, __func__ , ##args); \
} \
} while (0)
#else
#define PPC_IO_DPRINTF(fmt, args...) do { } while (0)
#endif
/* Constants for devices init */
static const int ide_iobase[2] = { 0x1f0, 0x170 };
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
static const int ide_irq[2] = { 13, 13 };
#define NE2000_NB_MAX 6
static uint32_t ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
//static PITState *pit;
/* ISA IO ports bridge */
#define PPC_IO_BASE 0x80000000
/* Speaker port 0x61 */
int speaker_data_on;
int dummy_refresh_clock;
static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
#if 0
speaker_data_on = (val >> 1) & 1;
pit_set_gate(pit, 2, val & 1);
#endif
}
static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
{
#if 0
int out;
out = pit_get_out(pit, 2, qemu_get_clock(vm_clock));
dummy_refresh_clock ^= 1;
return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
(dummy_refresh_clock << 4);
#endif
return 0;
}
/* PCI intack register */
/* Read-only register (?) */
static void _PPC_intack_write (void *opaque, target_phys_addr_t addr, uint32_t value)
{
// printf("%s: 0x%08x => 0x%08x\n", __func__, addr, value);
}
static inline uint32_t _PPC_intack_read (target_phys_addr_t addr)
{
uint32_t retval = 0;
if (addr == 0xBFFFFFF0)
retval = pic_intack_read(NULL);
// printf("%s: 0x%08x <= %d\n", __func__, addr, retval);
return retval;
}
static uint32_t PPC_intack_readb (void *opaque, target_phys_addr_t addr)
{
return _PPC_intack_read(addr);
}
static uint32_t PPC_intack_readw (void *opaque, target_phys_addr_t addr)
{
#ifdef TARGET_WORDS_BIGENDIAN
return bswap16(_PPC_intack_read(addr));
#else
return _PPC_intack_read(addr);
#endif
}
static uint32_t PPC_intack_readl (void *opaque, target_phys_addr_t addr)
{
#ifdef TARGET_WORDS_BIGENDIAN
return bswap32(_PPC_intack_read(addr));
#else
return _PPC_intack_read(addr);
#endif
}
static CPUWriteMemoryFunc *PPC_intack_write[] = {
&_PPC_intack_write,
&_PPC_intack_write,
&_PPC_intack_write,
};
static CPUReadMemoryFunc *PPC_intack_read[] = {
&PPC_intack_readb,
&PPC_intack_readw,
&PPC_intack_readl,
};
/* PowerPC control and status registers */
#if 0 // Not used
static struct {
/* IDs */
uint32_t veni_devi;
uint32_t revi;
/* Control and status */
uint32_t gcsr;
uint32_t xcfr;
uint32_t ct32;
uint32_t mcsr;
/* General purpose registers */
uint32_t gprg[6];
/* Exceptions */
uint32_t feen;
uint32_t fest;
uint32_t fema;
uint32_t fecl;
uint32_t eeen;
uint32_t eest;
uint32_t eecl;
uint32_t eeint;
uint32_t eemck0;
uint32_t eemck1;
/* Error diagnostic */
} XCSR;
static void PPC_XCSR_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
{
printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
}
static void PPC_XCSR_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap16(value);
#endif
printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
}
static void PPC_XCSR_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
#ifdef TARGET_WORDS_BIGENDIAN
value = bswap32(value);
#endif
printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
}
static uint32_t PPC_XCSR_readb (void *opaque, target_phys_addr_t addr)
{
uint32_t retval = 0;
printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
return retval;
}
static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr)
{
uint32_t retval = 0;
printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
#ifdef TARGET_WORDS_BIGENDIAN
retval = bswap16(retval);
#endif
return retval;
}
static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr)
{
uint32_t retval = 0;
printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
#ifdef TARGET_WORDS_BIGENDIAN
retval = bswap32(retval);
#endif
return retval;
}
static CPUWriteMemoryFunc *PPC_XCSR_write[] = {
&PPC_XCSR_writeb,
&PPC_XCSR_writew,
&PPC_XCSR_writel,
};
static CPUReadMemoryFunc *PPC_XCSR_read[] = {
&PPC_XCSR_readb,
&PPC_XCSR_readw,
&PPC_XCSR_readl,
};
#endif
/* Fake super-io ports for PREP platform (Intel 82378ZB) */
typedef struct sysctrl_t {
m48t59_t *nvram;
uint8_t state;
uint8_t syscontrol;
uint8_t fake_io[2];
} sysctrl_t;
enum {
STATE_HARDFILE = 0x01,
};
static sysctrl_t *sysctrl;
static void PREP_io_write (void *opaque, uint32_t addr, uint32_t val)
{
sysctrl_t *sysctrl = opaque;
PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
sysctrl->fake_io[addr - 0x0398] = val;
}
static uint32_t PREP_io_read (void *opaque, uint32_t addr)
{
sysctrl_t *sysctrl = opaque;
PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE,
sysctrl->fake_io[addr - 0x0398]);
return sysctrl->fake_io[addr - 0x0398];
}
static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
{
sysctrl_t *sysctrl = opaque;
PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
switch (addr) {
case 0x0092:
/* Special port 92 */
/* Check soft reset asked */
if (val & 0x01) {
// cpu_interrupt(cpu_single_env, CPU_INTERRUPT_RESET);
}
/* Check LE mode */
if (val & 0x02) {
printf("Little Endian mode isn't supported (yet ?)\n");
abort();
}
break;
case 0x0800:
/* Motorola CPU configuration register : read-only */
break;
case 0x0802:
/* Motorola base module feature register : read-only */
break;
case 0x0803:
/* Motorola base module status register : read-only */
break;
case 0x0808:
/* Hardfile light register */
if (val & 1)
sysctrl->state |= STATE_HARDFILE;
else
sysctrl->state &= ~STATE_HARDFILE;
break;
case 0x0810:
/* Password protect 1 register */
if (sysctrl->nvram != NULL)
m48t59_toggle_lock(sysctrl->nvram, 1);
break;
case 0x0812:
/* Password protect 2 register */
if (sysctrl->nvram != NULL)
m48t59_toggle_lock(sysctrl->nvram, 2);
break;
case 0x0814:
/* L2 invalidate register */
// tlb_flush(cpu_single_env, 1);
break;
case 0x081C:
/* system control register */
sysctrl->syscontrol = val & 0x0F;
break;
case 0x0850:
/* I/O map type register */
if (!(val & 0x01)) {
printf("No support for non-continuous I/O map mode\n");
abort();
}
break;
default:
printf("ERROR: unaffected IO port write: %04lx => %02x\n",
(long)addr, val);
break;
}
}
static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
{
sysctrl_t *sysctrl = opaque;
uint32_t retval = 0xFF;
switch (addr) {
case 0x0092:
/* Special port 92 */
retval = 0x00;
break;
case 0x0800:
/* Motorola CPU configuration register */
retval = 0xEF; /* MPC750 */
break;
case 0x0802:
/* Motorola Base module feature register */
retval = 0xAD; /* No ESCC, PMC slot neither ethernet */
break;
case 0x0803:
/* Motorola base module status register */
retval = 0xE0; /* Standard MPC750 */
break;
case 0x080C:
/* Equipment present register:
* no L2 cache
* no upgrade processor
* no cards in PCI slots
* SCSI fuse is bad
*/
retval = 0x3C;
break;
case 0x0810:
/* Motorola base module extended feature register */
retval = 0x39; /* No USB, CF and PCI bridge. NVRAM present */
break;
case 0x0818:
/* Keylock */
retval = 0x00;
break;
case 0x081C:
/* system control register
* 7 - 6 / 1 - 0: L2 cache enable
*/
retval = sysctrl->syscontrol;
break;
case 0x0823:
/* */
retval = 0x03; /* no L2 cache */
break;
case 0x0850:
/* I/O map type register */
retval = 0x01;
break;
default:
printf("ERROR: unaffected IO port: %04lx read\n", (long)addr);
break;
}
PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE, retval);
return retval;
}
extern CPUPPCState *global_env;
#define NVRAM_SIZE 0x2000
/* PowerPC PREP hardware initialisation */
void ppc_prep_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];
m48t59_t *nvram;
int PPC_io_memory;
int ret, linux_boot, i, nb_nics1, fd;
unsigned long bios_offset;
uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
PCIBus *pci_bus;
sysctrl = qemu_mallocz(sizeof(sysctrl_t));
if (sysctrl == NULL)
return;
linux_boot = (kernel_filename != NULL);
/* allocate RAM */
cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
/* allocate and load BIOS */
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) {
fprintf(stderr, "qemu: could not load PPC PREP bios '%s'\n", buf);
exit(1);
}
cpu_register_physical_memory((uint32_t)(-BIOS_SIZE),
BIOS_SIZE, bios_offset | IO_MEM_ROM);
cpu_single_env->nip = 0xfffffffc;
if (linux_boot) {
kernel_base = KERNEL_LOAD_ADDR;
/* now we can load the kernel */
kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
/* load initrd */
if (initrd_filename) {
initrd_base = INITRD_LOAD_ADDR;
initrd_size = load_image(initrd_filename,
phys_ram_base + initrd_base);
if (initrd_size < 0) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
} else {
initrd_base = 0;
initrd_size = 0;
}
boot_device = 'm';
} else {
kernel_base = 0;
kernel_size = 0;
initrd_base = 0;
initrd_size = 0;
}
/* Register CPU as a 74x/75x */
cpu_ppc_register(cpu_single_env, 0x00080000);
/* Set time-base frequency to 100 Mhz */
cpu_ppc_tb_init(cpu_single_env, 100UL * 1000UL * 1000UL);
isa_mem_base = 0xc0000000;
pci_bus = pci_prep_init();
/* Register 64 KB of ISA IO space */
PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
cpu_register_physical_memory(0x80000000, 0x00010000, PPC_io_memory);
/* init basic PC hardware */
vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
vga_ram_size);
rtc_init(0x70, 8);
// openpic = openpic_init(0x00000000, 0xF0000000, 1);
// pic_init(openpic);
pic_init();
// pit = pit_init(0x40, 0);
fd = serial_open_device();
serial_init(0x3f8, 4, fd);
nb_nics1 = nb_nics;
if (nb_nics1 > NE2000_NB_MAX)
nb_nics1 = NE2000_NB_MAX;
for(i = 0; i < nb_nics1; i++) {
isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]);
}
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]);
}
kbd_init();
DMA_init(1);
// AUD_init();
// SB16_init();
fdctrl_init(6, 2, 0, 0x3f0, fd_table);
/* Register speaker port */
register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
/* Register fake IO ports for PREP */
register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl);
/* System control ports */
register_ioport_read(0x0092, 0x01, 1, &PREP_io_800_readb, sysctrl);
register_ioport_write(0x0092, 0x01, 1, &PREP_io_800_writeb, sysctrl);
register_ioport_read(0x0800, 0x52, 1, &PREP_io_800_readb, sysctrl);
register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl);
/* PCI intack location */
PPC_io_memory = cpu_register_io_memory(0, PPC_intack_read,
PPC_intack_write, NULL);
cpu_register_physical_memory(0xBFFFFFF0, 0x4, PPC_io_memory);
/* PowerPC control and status register group */
#if 0
PPC_io_memory = cpu_register_io_memory(0, PPC_XCSR_read, PPC_XCSR_write, NULL);
cpu_register_physical_memory(0xFEFF0000, 0x1000, PPC_io_memory);
#endif
nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE);
if (nvram == NULL)
return;
sysctrl->nvram = nvram;
/* Initialise NVRAM */
PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
kernel_base, kernel_size,
kernel_cmdline,
initrd_base, initrd_size,
/* XXX: need an option to load a NVRAM image */
0,
graphic_width, graphic_height, graphic_depth);
}

762
hw/sb16.c Normal file
View File

@@ -0,0 +1,762 @@
/*
* QEMU Soundblaster 16 emulation
*
* Copyright (c) 2003 Vassili Karpov (malc)
*
* 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"
#define MIN(a, b) ((a)>(b)?(b):(a))
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
#define log(...) do { \
fprintf (stderr, "sb16: " __VA_ARGS__); \
fputc ('\n', stderr); \
} while (0)
/* #define DEBUG_SB16 */
#ifdef DEBUG_SB16
#define lwarn(...) fprintf (stderr, "sb16: " __VA_ARGS__)
#define linfo(...) fprintf (stderr, "sb16: " __VA_ARGS__)
#define ldebug(...) fprintf (stderr, "sb16: " __VA_ARGS__)
#else
#define lwarn(...)
#define linfo(...)
#define ldebug(...)
#endif
#define IO_READ_PROTO(name) \
uint32_t name (void *opaque, uint32_t nport)
#define IO_WRITE_PROTO(name) \
void name (void *opaque, uint32_t nport, uint32_t val)
static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
static struct {
int ver_lo;
int ver_hi;
int irq;
int dma;
int hdma;
int port;
int mix_block;
} sb = {5, 4, 5, 1, 5, 0x220, -1};
static int mix_block, noirq;
typedef struct SB16State {
int in_index;
int out_data_len;
int fmt_stereo;
int fmt_signed;
int fmt_bits;
int dma_auto;
int dma_buffer_size;
int fifo;
int freq;
int time_const;
int speaker;
int needed_bytes;
int cmd;
int dma_pos;
int use_hdma;
int v2x6;
uint8_t in_data[10];
uint8_t out_data[50];
int left_till_irq;
/* mixer state */
int mixer_nreg;
uint8_t mixer_regs[256];
} SB16State;
/* XXX: suppress that and use a context */
static struct SB16State dsp;
static void log_dsp (SB16State *dsp)
{
linfo ("%c:%c:%d:%c:dmabuf=%d:pos=%d:freq=%d:timeconst=%d:speaker=%d\n",
dsp->fmt_stereo ? 'S' : 'M',
dsp->fmt_signed ? 'S' : 'U',
dsp->fmt_bits,
dsp->dma_auto ? 'a' : 's',
dsp->dma_buffer_size,
dsp->dma_pos,
dsp->freq,
dsp->time_const,
dsp->speaker);
}
static void control (int hold)
{
linfo ("%d high %d\n", hold, dsp.use_hdma);
if (hold) {
if (dsp.use_hdma)
DMA_hold_DREQ (sb.hdma);
else
DMA_hold_DREQ (sb.dma);
}
else {
if (dsp.use_hdma)
DMA_release_DREQ (sb.hdma);
else
DMA_release_DREQ (sb.dma);
}
}
static void dma_cmd (uint8_t cmd, uint8_t d0, int dma_len)
{
int bps;
audfmt_e fmt;
dsp.use_hdma = cmd < 0xc0;
dsp.fifo = (cmd >> 1) & 1;
dsp.dma_auto = (cmd >> 2) & 1;
switch (cmd >> 4) {
case 11:
dsp.fmt_bits = 16;
break;
case 12:
dsp.fmt_bits = 8;
break;
}
dsp.fmt_signed = (d0 >> 4) & 1;
dsp.fmt_stereo = (d0 >> 5) & 1;
if (-1 != dsp.time_const) {
int tmp;
tmp = 256 - dsp.time_const;
dsp.freq = (1000000 + (tmp / 2)) / tmp;
}
bps = 1 << (16 == dsp.fmt_bits);
if (-1 != dma_len)
dsp.dma_buffer_size = (dma_len + 1) * bps;
linfo ("frequency %d, stereo %d, signed %d, bits %d, size %d, auto %d\n",
dsp.freq, dsp.fmt_stereo, dsp.fmt_signed, dsp.fmt_bits,
dsp.dma_buffer_size, dsp.dma_auto);
if (16 == dsp.fmt_bits) {
if (dsp.fmt_signed) {
fmt = AUD_FMT_S16;
}
else {
fmt = AUD_FMT_U16;
}
}
else {
if (dsp.fmt_signed) {
fmt = AUD_FMT_S8;
}
else {
fmt = AUD_FMT_U8;
}
}
dsp.dma_pos = 0;
dsp.left_till_irq = dsp.dma_buffer_size;
if (sb.mix_block) {
mix_block = sb.mix_block;
}
else {
int align;
align = bps << dsp.fmt_stereo;
mix_block = ((dsp.freq * align) / 100) & ~(align - 1);
}
AUD_reset (dsp.freq, 1 << dsp.fmt_stereo, fmt);
control (1);
dsp.speaker = 1;
}
static inline void dsp_out_data(SB16State *dsp, int val)
{
if (dsp->out_data_len < sizeof(dsp->out_data))
dsp->out_data[dsp->out_data_len++] = val;
}
static void command (SB16State *dsp, uint8_t cmd)
{
linfo ("%#x\n", cmd);
if (cmd > 0xaf && cmd < 0xd0) {
if (cmd & 8)
goto error;
switch (cmd >> 4) {
case 11:
case 12:
break;
default:
log("%#x wrong bits", cmd);
goto error;
}
dsp->needed_bytes = 3;
}
else {
switch (cmd) {
case 0x00:
case 0x03:
case 0xe7:
/* IMS uses those when probing for sound devices */
return;
case 0x04:
dsp->needed_bytes = 1;
break;
case 0x05:
case 0x0e:
dsp->needed_bytes = 2;
break;
case 0x0f:
dsp->needed_bytes = 1;
dsp_out_data (dsp, 0);
break;
case 0x10:
dsp->needed_bytes = 1;
break;
case 0x14:
dsp->needed_bytes = 2;
dsp->dma_buffer_size = 0;
break;
case 0x20:
dsp_out_data(dsp, 0xff);
break;
case 0x35:
lwarn ("MIDI commands not implemented\n");
break;
case 0x40:
dsp->freq = -1;
dsp->time_const = -1;
dsp->needed_bytes = 1;
break;
case 0x41:
case 0x42:
dsp->freq = -1;
dsp->time_const = -1;
dsp->needed_bytes = 2;
break;
case 0x47: /* Continue Auto-Initialize DMA 16bit */
break;
case 0x48:
dsp->needed_bytes = 2;
break;
case 0x27: /* ????????? */
case 0x4e:
return;
case 0x80:
cmd = -1;
break;
case 0x90:
case 0x91:
{
uint8_t d0;
d0 = 4;
/* if (dsp->fmt_signed) d0 |= 16; */
/* if (dsp->fmt_stereo) d0 |= 32; */
dma_cmd (cmd == 0x90 ? 0xc4 : 0xc0, d0, -1);
cmd = -1;
break;
}
case 0xd0: /* XXX */
control (0);
return;
case 0xd1:
dsp->speaker = 1;
break;
case 0xd3:
dsp->speaker = 0;
return;
case 0xd4:
control (1);
break;
case 0xd5:
control (0);
break;
case 0xd6:
control (1);
break;
case 0xd9:
control (0);
dsp->dma_auto = 0;
return;
case 0xda:
control (0);
dsp->dma_auto = 0;
break;
case 0xe0:
dsp->needed_bytes = 1;
break;
case 0xe1:
dsp_out_data(dsp, sb.ver_lo);
dsp_out_data(dsp, sb.ver_hi);
return;
case 0xe3:
{
int i;
for (i = sizeof (e3) - 1; i >= 0; --i)
dsp_out_data (dsp, e3[i]);
return;
}
case 0xf2:
dsp_out_data(dsp, 0xaa);
dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80];
pic_set_irq (sb.irq, 1);
return;
default:
log("%#x is unknown", cmd);
goto error;
}
}
dsp->cmd = cmd;
return;
error:
return;
}
static void complete (SB16State *dsp)
{
linfo ("complete command %#x, in_index %d, needed_bytes %d\n",
dsp->cmd, dsp->in_index, dsp->needed_bytes);
if (dsp->cmd > 0xaf && dsp->cmd < 0xd0) {
int d0, d1, d2;
d0 = dsp->in_data[0];
d1 = dsp->in_data[1];
d2 = dsp->in_data[2];
ldebug ("d0 = %d, d1 = %d, d2 = %d\n",
d0, d1, d2);
dma_cmd (dsp->cmd, d0, d1 + (d2 << 8));
}
else {
switch (dsp->cmd) {
case 0x05:
case 0x04:
case 0x0e:
case 0x0f:
break;
case 0x10:
break;
case 0x14:
{
int d0, d1;
int save_left;
int save_pos;
d0 = dsp->in_data[0];
d1 = dsp->in_data[1];
save_left = dsp->left_till_irq;
save_pos = dsp->dma_pos;
dma_cmd (0xc0, 0, d0 + (d1 << 8));
dsp->left_till_irq = save_left;
dsp->dma_pos = save_pos;
linfo ("set buffer size data[%d, %d] %d pos %d\n",
d0, d1, dsp->dma_buffer_size, dsp->dma_pos);
break;
}
case 0x40:
dsp->time_const = dsp->in_data[0];
linfo ("set time const %d\n", dsp->time_const);
break;
case 0x41:
case 0x42:
dsp->freq = dsp->in_data[1] + (dsp->in_data[0] << 8);
linfo ("set freq %#x, %#x = %d\n",
dsp->in_data[1], dsp->in_data[0], dsp->freq);
break;
case 0x48:
dsp->dma_buffer_size = dsp->in_data[1] + (dsp->in_data[0] << 8);
linfo ("set dma len %#x, %#x = %d\n",
dsp->in_data[1], dsp->in_data[0], dsp->dma_buffer_size);
break;
case 0xe0:
dsp->out_data_len = 0;
linfo ("data = %#x\n", dsp->in_data[0]);
dsp_out_data(dsp, dsp->in_data[0] ^ 0xff);
break;
default:
log ("unrecognized command %#x", dsp->cmd);
return;
}
}
dsp->cmd = -1;
return;
}
static IO_WRITE_PROTO (dsp_write)
{
SB16State *dsp = opaque;
int iport;
iport = nport - sb.port;
ldebug ("write %#x %#x\n", nport, iport);
switch (iport) {
case 0x6:
control (0);
if (0 == val)
dsp->v2x6 = 0;
else if ((1 == val) && (0 == dsp->v2x6)) {
dsp->v2x6 = 1;
dsp_out_data(dsp, 0xaa);
}
else
dsp->v2x6 = ~0;
break;
case 0xc: /* write data or command | write status */
if (0 == dsp->needed_bytes) {
command (dsp, val);
if (0 == dsp->needed_bytes) {
log_dsp (dsp);
}
}
else {
dsp->in_data[dsp->in_index++] = val;
if (dsp->in_index == dsp->needed_bytes) {
dsp->needed_bytes = 0;
dsp->in_index = 0;
complete (dsp);
log_dsp (dsp);
}
}
break;
default:
log ("(nport=%#x, val=%#x)", nport, val);
break;
}
}
static IO_READ_PROTO (dsp_read)
{
SB16State *dsp = opaque;
int iport, retval;
iport = nport - sb.port;
switch (iport) {
case 0x6: /* reset */
return 0;
case 0xa: /* read data */
if (dsp->out_data_len) {
retval = dsp->out_data[--dsp->out_data_len];
} else {
log("empty output buffer");
goto error;
}
break;
case 0xc: /* 0 can write */
retval = 0;
break;
case 0xd: /* timer interrupt clear */
log("timer interrupt clear");
goto error;
case 0xe: /* data available status | irq 8 ack */
/* XXX drop pic irq line here? */
ldebug ("8 ack\n");
retval = (0 == dsp->out_data_len) ? 0 : 0x80;
dsp->mixer_regs[0x82] &= ~dsp->mixer_regs[0x80];
pic_set_irq (sb.irq, 0);
break;
case 0xf: /* irq 16 ack */
/* XXX drop pic irq line here? */
ldebug ("16 ack\n");
retval = 0xff;
dsp->mixer_regs[0x82] &= ~dsp->mixer_regs[0x80];
pic_set_irq (sb.irq, 0);
break;
default:
goto error;
}
if ((0xc != iport) && (0xe != iport)) {
ldebug ("nport=%#x iport %#x = %#x\n",
nport, iport, retval);
}
return retval;
error:
return 0;
}
static IO_WRITE_PROTO(mixer_write_indexb)
{
SB16State *dsp = opaque;
dsp->mixer_nreg = val;
}
static IO_WRITE_PROTO(mixer_write_datab)
{
SB16State *dsp = opaque;
if (dsp->mixer_nreg > 0x83)
return;
dsp->mixer_regs[dsp->mixer_nreg] = val;
}
static IO_WRITE_PROTO(mixer_write_indexw)
{
mixer_write_indexb (opaque, nport, val & 0xff);
mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
}
static IO_READ_PROTO(mixer_read)
{
SB16State *dsp = opaque;
return dsp->mixer_regs[dsp->mixer_nreg];
}
void SB16_run (void)
{
if (0 == dsp.speaker)
return;
AUD_run ();
}
static int write_audio (uint32_t addr, int len, int size)
{
int temp, net;
uint8_t tmpbuf[4096];
temp = size;
net = 0;
while (temp) {
int left_till_end;
int to_copy;
int copied;
left_till_end = len - dsp.dma_pos;
to_copy = MIN (temp, left_till_end);
if (to_copy > sizeof(tmpbuf))
to_copy = sizeof(tmpbuf);
cpu_physical_memory_read(addr + dsp.dma_pos, tmpbuf, to_copy);
copied = AUD_write (tmpbuf, to_copy);
temp -= copied;
dsp.dma_pos += copied;
if (dsp.dma_pos == len) {
dsp.dma_pos = 0;
}
net += copied;
if (copied != to_copy)
return net;
}
return net;
}
static int SB_read_DMA (void *opaque, target_ulong addr, int size)
{
SB16State *dsp = opaque;
int free, till, copy, written;
if (0 == dsp->speaker)
return 0;
if (dsp->left_till_irq < 0) {
dsp->left_till_irq += dsp->dma_buffer_size;
return dsp->dma_pos;
}
free = AUD_get_free ();
if ((free <= 0) || (0 == size)) {
return dsp->dma_pos;
}
if (mix_block > 0) {
copy = MIN (free, mix_block);
}
else {
copy = free;
}
till = dsp->left_till_irq;
ldebug ("addr:%#010x free:%d till:%d size:%d\n",
addr, free, till, size);
if (till <= copy) {
if (0 == dsp->dma_auto) {
copy = till;
}
}
written = write_audio (addr, size, copy);
dsp->left_till_irq -= written;
AUD_adjust_estimate (free - written);
if (dsp->left_till_irq <= 0) {
dsp->mixer_regs[0x82] |= dsp->mixer_regs[0x80];
if (0 == noirq) {
ldebug ("request irq\n");
pic_set_irq(sb.irq, 1);
}
if (0 == dsp->dma_auto) {
control (0);
}
}
ldebug ("pos %5d free %5d size %5d till % 5d copy %5d dma size %5d\n",
dsp->dma_pos, free, size, dsp->left_till_irq, copy,
dsp->dma_buffer_size);
if (dsp->left_till_irq <= 0) {
dsp->left_till_irq += dsp->dma_buffer_size;
}
return dsp->dma_pos;
}
static int magic_of_irq (int irq)
{
switch (irq) {
case 2:
return 1;
case 5:
return 2;
case 7:
return 4;
case 10:
return 8;
default:
log ("bad irq %d", irq);
return 2;
}
}
#if 0
static int irq_of_magic (int magic)
{
switch (magic) {
case 1:
return 2;
case 2:
return 5;
case 4:
return 7;
case 8:
return 10;
default:
log ("bad irq magic %d", magic);
return 2;
}
}
#endif
void SB16_init (void)
{
SB16State *s = &dsp;
int i;
static const uint8_t dsp_write_ports[] = {0x6, 0xc};
static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
memset(s->mixer_regs, 0xff, sizeof(s->mixer_regs));
s->mixer_regs[0x0e] = ~0;
s->mixer_regs[0x80] = magic_of_irq (sb.irq);
s->mixer_regs[0x81] = 0x20 | (sb.dma << 1);
for (i = 0x30; i < 0x48; i++) {
s->mixer_regs[i] = 0x20;
}
for (i = 0; i < LENOFA (dsp_write_ports); i++) {
register_ioport_write (sb.port + dsp_write_ports[i], 1, 1, dsp_write, s);
}
for (i = 0; i < LENOFA (dsp_read_ports); i++) {
register_ioport_read (sb.port + dsp_read_ports[i], 1, 1, dsp_read, s);
}
register_ioport_write (sb.port + 0x4, 1, 1, mixer_write_indexb, s);
register_ioport_write (sb.port + 0x4, 1, 2, mixer_write_indexw, s);
register_ioport_read (sb.port + 0x5, 1, 1, mixer_read, s);
register_ioport_write (sb.port + 0x5, 1, 1, mixer_write_datab, s);
DMA_register_channel (sb.hdma, SB_read_DMA, s);
DMA_register_channel (sb.dma, SB_read_DMA, s);
}

283
hw/serial.c Normal file
View File

@@ -0,0 +1,283 @@
/*
* QEMU 16450 UART emulation
*
* Copyright (c) 2003-2004 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"
//#define DEBUG_SERIAL
#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
#define UART_IIR_MSI 0x00 /* Modem status interrupt */
#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
/*
* These are the definitions for the Modem Control Register
*/
#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
#define UART_MCR_OUT2 0x08 /* Out2 complement */
#define UART_MCR_OUT1 0x04 /* Out1 complement */
#define UART_MCR_RTS 0x02 /* RTS complement */
#define UART_MCR_DTR 0x01 /* DTR complement */
/*
* These are the definitions for the Modem Status Register
*/
#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
#define UART_MSR_RI 0x40 /* Ring Indicator */
#define UART_MSR_DSR 0x20 /* Data Set Ready */
#define UART_MSR_CTS 0x10 /* Clear to Send */
#define UART_MSR_DDCD 0x08 /* Delta DCD */
#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
#define UART_MSR_DDSR 0x02 /* Delta DSR */
#define UART_MSR_DCTS 0x01 /* Delta CTS */
#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */
#define UART_LSR_TEMT 0x40 /* Transmitter empty */
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
#define UART_LSR_BI 0x10 /* Break interrupt indicator */
#define UART_LSR_FE 0x08 /* Frame error indicator */
#define UART_LSR_PE 0x04 /* Parity error indicator */
#define UART_LSR_OE 0x02 /* Overrun error indicator */
#define UART_LSR_DR 0x01 /* Receiver data ready */
struct SerialState {
uint8_t divider;
uint8_t rbr; /* receive register */
uint8_t ier;
uint8_t iir; /* read only */
uint8_t lcr;
uint8_t mcr;
uint8_t lsr; /* read only */
uint8_t msr;
uint8_t scr;
/* NOTE: this hidden state is necessary for tx irq generation as
it can be reset while reading iir */
int thr_ipending;
int irq;
int out_fd;
};
static void serial_update_irq(SerialState *s)
{
if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) {
s->iir = UART_IIR_RDI;
} else if (s->thr_ipending && (s->ier & UART_IER_THRI)) {
s->iir = UART_IIR_THRI;
} else {
s->iir = UART_IIR_NO_INT;
}
if (s->iir != UART_IIR_NO_INT) {
pic_set_irq(s->irq, 1);
} else {
pic_set_irq(s->irq, 0);
}
}
static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
{
SerialState *s = opaque;
unsigned char ch;
int ret;
addr &= 7;
#ifdef DEBUG_SERIAL
printf("serial: write addr=0x%02x val=0x%02x\n", addr, val);
#endif
switch(addr) {
default:
case 0:
if (s->lcr & UART_LCR_DLAB) {
s->divider = (s->divider & 0xff00) | val;
} else {
s->thr_ipending = 0;
s->lsr &= ~UART_LSR_THRE;
serial_update_irq(s);
if (s->out_fd >= 0) {
ch = val;
do {
ret = write(s->out_fd, &ch, 1);
} while (ret != 1);
}
s->thr_ipending = 1;
s->lsr |= UART_LSR_THRE;
s->lsr |= UART_LSR_TEMT;
serial_update_irq(s);
}
break;
case 1:
if (s->lcr & UART_LCR_DLAB) {
s->divider = (s->divider & 0x00ff) | (val << 8);
} else {
s->ier = val;
serial_update_irq(s);
}
break;
case 2:
break;
case 3:
s->lcr = val;
break;
case 4:
s->mcr = val;
break;
case 5:
break;
case 6:
s->msr = val;
break;
case 7:
s->scr = val;
break;
}
}
static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
{
SerialState *s = opaque;
uint32_t ret;
addr &= 7;
switch(addr) {
default:
case 0:
if (s->lcr & UART_LCR_DLAB) {
ret = s->divider & 0xff;
} else {
ret = s->rbr;
s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
serial_update_irq(s);
}
break;
case 1:
if (s->lcr & UART_LCR_DLAB) {
ret = (s->divider >> 8) & 0xff;
} else {
ret = s->ier;
}
break;
case 2:
ret = s->iir;
/* reset THR pending bit */
if ((ret & 0x7) == UART_IIR_THRI)
s->thr_ipending = 0;
serial_update_irq(s);
break;
case 3:
ret = s->lcr;
break;
case 4:
ret = s->mcr;
break;
case 5:
ret = s->lsr;
break;
case 6:
if (s->mcr & UART_MCR_LOOP) {
/* in loopback, the modem output pins are connected to the
inputs */
ret = (s->mcr & 0x0c) << 4;
ret |= (s->mcr & 0x02) << 3;
ret |= (s->mcr & 0x01) << 5;
} else {
ret = s->msr;
}
break;
case 7:
ret = s->scr;
break;
}
#ifdef DEBUG_SERIAL
printf("serial: read addr=0x%02x val=0x%02x\n", addr, ret);
#endif
return ret;
}
int serial_can_receive(SerialState *s)
{
return !(s->lsr & UART_LSR_DR);
}
void serial_receive_byte(SerialState *s, int ch)
{
s->rbr = ch;
s->lsr |= UART_LSR_DR;
serial_update_irq(s);
}
void serial_receive_break(SerialState *s)
{
s->rbr = 0;
s->lsr |= UART_LSR_BI | UART_LSR_DR;
serial_update_irq(s);
}
static int serial_can_receive1(void *opaque)
{
SerialState *s = opaque;
return serial_can_receive(s);
}
static void serial_receive1(void *opaque, const uint8_t *buf, int size)
{
SerialState *s = opaque;
serial_receive_byte(s, buf[0]);
}
/* If fd is zero, it means that the serial device uses the console */
SerialState *serial_init(int base, int irq, int fd)
{
SerialState *s;
s = qemu_mallocz(sizeof(SerialState));
if (!s)
return NULL;
s->irq = irq;
s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
s->iir = UART_IIR_NO_INT;
register_ioport_write(base, 8, 1, serial_ioport_write, s);
register_ioport_read(base, 8, 1, serial_ioport_read, s);
if (fd < 0) {
/* no associated device */
s->out_fd = -1;
} else if (fd != 0) {
qemu_add_fd_read_handler(fd, serial_can_receive1, serial_receive1, s);
s->out_fd = fd;
} else {
serial_console = s;
s->out_fd = 1;
}
return s;
}

1917
hw/vga.c Normal file

File diff suppressed because it is too large Load Diff

167
hw/vga_int.h Normal file
View File

@@ -0,0 +1,167 @@
/*
* QEMU internal VGA defines.
*
* Copyright (c) 2003-2004 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.
*/
#define MSR_COLOR_EMULATION 0x01
#define MSR_PAGE_SELECT 0x20
#define ST01_V_RETRACE 0x08
#define ST01_DISP_ENABLE 0x01
/* bochs VBE support */
#define CONFIG_BOCHS_VBE
#define VBE_DISPI_MAX_XRES 1024
#define VBE_DISPI_MAX_YRES 768
#define VBE_DISPI_INDEX_ID 0x0
#define VBE_DISPI_INDEX_XRES 0x1
#define VBE_DISPI_INDEX_YRES 0x2
#define VBE_DISPI_INDEX_BPP 0x3
#define VBE_DISPI_INDEX_ENABLE 0x4
#define VBE_DISPI_INDEX_BANK 0x5
#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
#define VBE_DISPI_INDEX_X_OFFSET 0x8
#define VBE_DISPI_INDEX_Y_OFFSET 0x9
#define VBE_DISPI_INDEX_NB 0xa
#define VBE_DISPI_ID0 0xB0C0
#define VBE_DISPI_ID1 0xB0C1
#define VBE_DISPI_ID2 0xB0C2
#define VBE_DISPI_DISABLED 0x00
#define VBE_DISPI_ENABLED 0x01
#define VBE_DISPI_LFB_ENABLED 0x40
#define VBE_DISPI_NOCLEARMEM 0x80
#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000
#ifdef CONFIG_BOCHS_VBE
#define VGA_STATE_COMMON_BOCHS_VBE \
uint16_t vbe_index; \
uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; \
uint32_t vbe_start_addr; \
uint32_t vbe_line_offset; \
uint32_t vbe_bank_mask;
#else
#define VGA_STATE_COMMON_BOCHS_VBE
#endif /* !CONFIG_BOCHS_VBE */
#define CH_ATTR_SIZE (160 * 100)
#define VGA_MAX_HEIGHT 1024
#define VGA_STATE_COMMON \
uint8_t *vram_ptr; \
unsigned long vram_offset; \
unsigned int vram_size; \
uint32_t latch; \
uint8_t sr_index; \
uint8_t sr[256]; \
uint8_t gr_index; \
uint8_t gr[256]; \
uint8_t ar_index; \
uint8_t ar[21]; \
int ar_flip_flop; \
uint8_t cr_index; \
uint8_t cr[256]; /* CRT registers */ \
uint8_t msr; /* Misc Output Register */ \
uint8_t fcr; /* Feature Control Register */ \
uint8_t st00; /* status 0 */ \
uint8_t st01; /* status 1 */ \
uint8_t dac_state; \
uint8_t dac_sub_index; \
uint8_t dac_read_index; \
uint8_t dac_write_index; \
uint8_t dac_cache[3]; /* used when writing */ \
uint8_t palette[768]; \
int32_t bank_offset; \
int (*get_bpp)(struct VGAState *s); \
void (*get_offsets)(struct VGAState *s, \
uint32_t *pline_offset, \
uint32_t *pstart_addr); \
void (*get_resolution)(struct VGAState *s, \
int *pwidth, \
int *pheight); \
VGA_STATE_COMMON_BOCHS_VBE \
/* display refresh support */ \
DisplayState *ds; \
uint32_t font_offsets[2]; \
int graphic_mode; \
uint8_t shift_control; \
uint8_t double_scan; \
uint32_t line_offset; \
uint32_t line_compare; \
uint32_t start_addr; \
uint8_t last_cw, last_ch; \
uint32_t last_width, last_height; /* in chars or pixels */ \
uint32_t last_scr_width, last_scr_height; /* in pixels */ \
uint8_t cursor_start, cursor_end; \
uint32_t cursor_offset; \
unsigned int (*rgb_to_pixel)(unsigned int r, \
unsigned int g, unsigned b); \
/* hardware mouse cursor support */ \
uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; \
void (*cursor_invalidate)(struct VGAState *s); \
void (*cursor_draw_line)(struct VGAState *s, uint8_t *d, int y); \
/* tell for each page if it has been updated since the last time */ \
uint32_t last_palette[256]; \
uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
typedef struct VGAState {
VGA_STATE_COMMON
} VGAState;
static inline int c6_to_8(int v)
{
int b;
v &= 0x3f;
b = v & 1;
return (v << 2) | (b << 1) | b;
}
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
unsigned long vga_ram_offset, int vga_ram_size);
uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr);
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val);
void vga_invalidate_scanlines(VGAState *s, int y1, int y2);
void vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1,
int poffset, int w,
unsigned int color0, unsigned int color1,
unsigned int color_xor);
void vga_draw_cursor_line_16(uint8_t *d1, const uint8_t *src1,
int poffset, int w,
unsigned int color0, unsigned int color1,
unsigned int color_xor);
void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1,
int poffset, int w,
unsigned int color0, unsigned int color1,
unsigned int color_xor);
extern const uint8_t sr_mask[8];
extern const uint8_t gr_mask[16];

520
hw/vga_template.h Normal file
View File

@@ -0,0 +1,520 @@
/*
* QEMU VGA Emulator templates
*
* Copyright (c) 2003 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.
*/
#if DEPTH == 8
#define BPP 1
#define PIXEL_TYPE uint8_t
#elif DEPTH == 15 || DEPTH == 16
#define BPP 2
#define PIXEL_TYPE uint16_t
#elif DEPTH == 32
#define BPP 4
#define PIXEL_TYPE uint32_t
#else
#error unsupport depth
#endif
#if DEPTH != 15
static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d,
uint32_t font_data,
uint32_t xorcol,
uint32_t bgcol)
{
#if BPP == 1
((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
((uint32_t *)d)[3] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
#elif BPP == 2
((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
#else
((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
#endif
}
static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
const uint8_t *font_ptr, int h,
uint32_t fgcol, uint32_t bgcol)
{
uint32_t font_data, xorcol;
xorcol = bgcol ^ fgcol;
do {
font_data = font_ptr[0];
glue(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol);
font_ptr += 4;
d += linesize;
} while (--h);
}
static void glue(vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize,
const uint8_t *font_ptr, int h,
uint32_t fgcol, uint32_t bgcol)
{
uint32_t font_data, xorcol;
xorcol = bgcol ^ fgcol;
do {
font_data = font_ptr[0];
glue(vga_draw_glyph_line_, DEPTH)(d,
expand4to8[font_data >> 4],
xorcol, bgcol);
glue(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP,
expand4to8[font_data & 0x0f],
xorcol, bgcol);
font_ptr += 4;
d += linesize;
} while (--h);
}
static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize,
const uint8_t *font_ptr, int h,
uint32_t fgcol, uint32_t bgcol, int dup9)
{
uint32_t font_data, xorcol, v;
xorcol = bgcol ^ fgcol;
do {
font_data = font_ptr[0];
/* XXX: unaligned accesses are done */
#if BPP == 1
((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
((uint32_t *)d)[3] = v;
if (dup9)
((uint8_t *)d)[8] = v >> (24 * (1 - BIG));
else
((uint8_t *)d)[8] = bgcol;
#elif BPP == 2
((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
((uint32_t *)d)[3] = v;
if (dup9)
((uint16_t *)d)[8] = v >> (16 * (1 - BIG));
else
((uint16_t *)d)[8] = bgcol;
#else
((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
((uint32_t *)d)[7] = v;
if (dup9)
((uint32_t *)d)[8] = v;
else
((uint32_t *)d)[8] = bgcol;
#endif
font_ptr += 4;
d += linesize;
} while (--h);
}
/*
* 4 color mode
*/
static void glue(vga_draw_line2_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
uint32_t plane_mask, *palette, data, v;
int x;
palette = s1->last_palette;
plane_mask = mask16[s1->ar[0x12] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
data &= plane_mask;
v = expand2[GET_PLANE(data, 0)];
v |= expand2[GET_PLANE(data, 2)] << 2;
((PIXEL_TYPE *)d)[0] = palette[v >> 12];
((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf];
((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf];
((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf];
v = expand2[GET_PLANE(data, 1)];
v |= expand2[GET_PLANE(data, 3)] << 2;
((PIXEL_TYPE *)d)[4] = palette[v >> 12];
((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
d += BPP * 8;
s += 4;
}
}
#if BPP == 1
#define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v)
#elif BPP == 2
#define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v)
#else
#define PUT_PIXEL2(d, n, v) \
((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
#endif
/*
* 4 color mode, dup2 horizontal
*/
static void glue(vga_draw_line2d2_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
uint32_t plane_mask, *palette, data, v;
int x;
palette = s1->last_palette;
plane_mask = mask16[s1->ar[0x12] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
data &= plane_mask;
v = expand2[GET_PLANE(data, 0)];
v |= expand2[GET_PLANE(data, 2)] << 2;
PUT_PIXEL2(d, 0, palette[v >> 12]);
PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
v = expand2[GET_PLANE(data, 1)];
v |= expand2[GET_PLANE(data, 3)] << 2;
PUT_PIXEL2(d, 4, palette[v >> 12]);
PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
d += BPP * 16;
s += 4;
}
}
/*
* 16 color mode
*/
static void glue(vga_draw_line4_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
uint32_t plane_mask, data, v, *palette;
int x;
palette = s1->last_palette;
plane_mask = mask16[s1->ar[0x12] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
data &= plane_mask;
v = expand4[GET_PLANE(data, 0)];
v |= expand4[GET_PLANE(data, 1)] << 1;
v |= expand4[GET_PLANE(data, 2)] << 2;
v |= expand4[GET_PLANE(data, 3)] << 3;
((PIXEL_TYPE *)d)[0] = palette[v >> 28];
((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf];
((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf];
((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf];
((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf];
((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
d += BPP * 8;
s += 4;
}
}
/*
* 16 color mode, dup2 horizontal
*/
static void glue(vga_draw_line4d2_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
uint32_t plane_mask, data, v, *palette;
int x;
palette = s1->last_palette;
plane_mask = mask16[s1->ar[0x12] & 0xf];
width >>= 3;
for(x = 0; x < width; x++) {
data = ((uint32_t *)s)[0];
data &= plane_mask;
v = expand4[GET_PLANE(data, 0)];
v |= expand4[GET_PLANE(data, 1)] << 1;
v |= expand4[GET_PLANE(data, 2)] << 2;
v |= expand4[GET_PLANE(data, 3)] << 3;
PUT_PIXEL2(d, 0, palette[v >> 28]);
PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
d += BPP * 16;
s += 4;
}
}
/*
* 256 color mode, double pixels
*
* XXX: add plane_mask support (never used in standard VGA modes)
*/
static void glue(vga_draw_line8d2_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
uint32_t *palette;
int x;
palette = s1->last_palette;
width >>= 3;
for(x = 0; x < width; x++) {
PUT_PIXEL2(d, 0, palette[s[0]]);
PUT_PIXEL2(d, 1, palette[s[1]]);
PUT_PIXEL2(d, 2, palette[s[2]]);
PUT_PIXEL2(d, 3, palette[s[3]]);
d += BPP * 8;
s += 4;
}
}
/*
* standard 256 color mode
*
* XXX: add plane_mask support (never used in standard VGA modes)
*/
static void glue(vga_draw_line8_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
uint32_t *palette;
int x;
palette = s1->last_palette;
width >>= 3;
for(x = 0; x < width; x++) {
((PIXEL_TYPE *)d)[0] = palette[s[0]];
((PIXEL_TYPE *)d)[1] = palette[s[1]];
((PIXEL_TYPE *)d)[2] = palette[s[2]];
((PIXEL_TYPE *)d)[3] = palette[s[3]];
((PIXEL_TYPE *)d)[4] = palette[s[4]];
((PIXEL_TYPE *)d)[5] = palette[s[5]];
((PIXEL_TYPE *)d)[6] = palette[s[6]];
((PIXEL_TYPE *)d)[7] = palette[s[7]];
d += BPP * 8;
s += 8;
}
}
#endif /* DEPTH != 15 */
/* XXX: optimize */
/*
* 15 bit color
*/
static void glue(vga_draw_line15_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
#if DEPTH == 15 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
memcpy(d, s, width * 2);
#else
int w;
uint32_t v, r, g, b;
w = width;
do {
v = lduw_raw((void *)s);
r = (v >> 7) & 0xf8;
g = (v >> 2) & 0xf8;
b = (v << 3) & 0xf8;
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
s += 2;
d += BPP;
} while (--w != 0);
#endif
}
/*
* 16 bit color
*/
static void glue(vga_draw_line16_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
memcpy(d, s, width * 2);
#else
int w;
uint32_t v, r, g, b;
w = width;
do {
v = lduw_raw((void *)s);
r = (v >> 8) & 0xf8;
g = (v >> 3) & 0xfc;
b = (v << 3) & 0xf8;
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
s += 2;
d += BPP;
} while (--w != 0);
#endif
}
/*
* 24 bit color
*/
static void glue(vga_draw_line24_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
int w;
uint32_t r, g, b;
w = width;
do {
#if defined(TARGET_WORDS_BIGENDIAN)
r = s[0];
g = s[1];
b = s[2];
#else
b = s[0];
g = s[1];
r = s[2];
#endif
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
s += 3;
d += BPP;
} while (--w != 0);
}
/*
* 32 bit color
*/
static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d,
const uint8_t *s, int width)
{
#if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
memcpy(d, s, width * 4);
#else
int w;
uint32_t r, g, b;
w = width;
do {
#if defined(TARGET_WORDS_BIGENDIAN)
r = s[1];
g = s[2];
b = s[3];
#else
b = s[0];
g = s[1];
r = s[2];
#endif
((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
s += 4;
d += BPP;
} while (--w != 0);
#endif
}
#if DEPTH != 15
void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1,
const uint8_t *src1,
int poffset, int w,
unsigned int color0,
unsigned int color1,
unsigned int color_xor)
{
const uint8_t *plane0, *plane1;
int x, b0, b1;
uint8_t *d;
d = d1;
plane0 = src1;
plane1 = src1 + poffset;
for(x = 0; x < w; x++) {
b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
#if DEPTH == 8
switch(b0 | (b1 << 1)) {
case 0:
break;
case 1:
d[0] ^= color_xor;
break;
case 2:
d[0] = color0;
break;
case 3:
d[0] = color1;
break;
}
#elif DEPTH == 16
switch(b0 | (b1 << 1)) {
case 0:
break;
case 1:
((uint16_t *)d)[0] ^= color_xor;
break;
case 2:
((uint16_t *)d)[0] = color0;
break;
case 3:
((uint16_t *)d)[0] = color1;
break;
}
#elif DEPTH == 32
switch(b0 | (b1 << 1)) {
case 0:
break;
case 1:
((uint32_t *)d)[0] ^= color_xor;
break;
case 2:
((uint32_t *)d)[0] = color0;
break;
case 3:
((uint32_t *)d)[0] = color1;
break;
}
#else
#error unsupported depth
#endif
d += BPP;
}
}
#endif
#undef PUT_PIXEL2
#undef DEPTH
#undef BPP
#undef PIXEL_TYPE

4475
i386-dis.c

File diff suppressed because it is too large Load Diff

10
i386.ld
View File

@@ -53,6 +53,16 @@ SECTIONS
_etext = .;
PROVIDE (etext = .);
.fini : { *(.fini) } =0x47ff041f
. = ALIGN(32 / 8);
PROVIDE (__preinit_array_start = .);
.preinit_array : { *(.preinit_array) }
PROVIDE (__preinit_array_end = .);
PROVIDE (__init_array_start = .);
.init_array : { *(.init_array) }
PROVIDE (__init_array_end = .);
PROVIDE (__fini_array_start = .);
.fini_array : { *(.fini_array) }
PROVIDE (__fini_array_end = .);
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
.rodata1 : { *(.rodata1) }
.reginfo : { *(.reginfo) }

305
linux-2.6-qemu-fast.patch Normal file
View File

@@ -0,0 +1,305 @@
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/arch/i386/Kconfig .32324-linux-2.6.0.updated/arch/i386/Kconfig
--- .32324-linux-2.6.0/arch/i386/Kconfig 2003-10-09 18:02:48.000000000 +1000
+++ .32324-linux-2.6.0.updated/arch/i386/Kconfig 2003-12-26 16:46:49.000000000 +1100
@@ -307,6 +307,14 @@ config X86_GENERIC
when it has moderate overhead. This is intended for generic
distributions kernels.
+config QEMU
+ bool "Kernel to run under QEMU"
+ depends on EXPERIMENTAL
+ help
+ Select this if you want to boot the kernel inside qemu-fast,
+ the non-mmu version of the x86 emulator. See
+ <http://fabrice.bellard.free.fr/qemu/>. Say N.
+
#
# Define implied options from the CPU selection here
#
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/arch/i386/kernel/Makefile .32324-linux-2.6.0.updated/arch/i386/kernel/Makefile
--- .32324-linux-2.6.0/arch/i386/kernel/Makefile 2003-09-29 10:25:15.000000000 +1000
+++ .32324-linux-2.6.0.updated/arch/i386/kernel/Makefile 2003-12-26 16:46:49.000000000 +1100
@@ -46,12 +46,14 @@ quiet_cmd_syscall = SYSCALL $@
cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \
-Wl,-T,$(filter-out FORCE,$^) -o $@
+export AFLAGS_vsyscall.lds.o += -P -C -U$(ARCH)
+
vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1
SYSCFLAGS_vsyscall-sysenter.so = $(vsyscall-flags)
SYSCFLAGS_vsyscall-int80.so = $(vsyscall-flags)
$(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so: \
-$(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
+$(obj)/vsyscall-%.so: $(src)/vsyscall.lds.s $(obj)/vsyscall-%.o FORCE
$(call if_changed,syscall)
# We also create a special relocatable object that should mirror the symbol
@@ -62,5 +64,5 @@ $(obj)/built-in.o: $(obj)/vsyscall-syms.
$(obj)/built-in.o: ld_flags += -R $(obj)/vsyscall-syms.o
SYSCFLAGS_vsyscall-syms.o = -r
-$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds $(obj)/vsyscall-sysenter.o FORCE
+$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds.s $(obj)/vsyscall-sysenter.o FORCE
$(call if_changed,syscall)
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/arch/i386/kernel/vmlinux.lds.S .32324-linux-2.6.0.updated/arch/i386/kernel/vmlinux.lds.S
--- .32324-linux-2.6.0/arch/i386/kernel/vmlinux.lds.S 2003-09-22 10:27:28.000000000 +1000
+++ .32324-linux-2.6.0.updated/arch/i386/kernel/vmlinux.lds.S 2003-12-26 16:46:49.000000000 +1100
@@ -3,6 +3,7 @@
*/
#include <asm-generic/vmlinux.lds.h>
+#include <asm/page.h>
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
@@ -10,7 +11,7 @@ ENTRY(startup_32)
jiffies = jiffies_64;
SECTIONS
{
- . = 0xC0000000 + 0x100000;
+ . = __PAGE_OFFSET + 0x100000;
/* read-only */
_text = .; /* Text and read-only data */
.text : {
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/arch/i386/kernel/vsyscall.lds .32324-linux-2.6.0.updated/arch/i386/kernel/vsyscall.lds
--- .32324-linux-2.6.0/arch/i386/kernel/vsyscall.lds 2003-09-22 10:07:26.000000000 +1000
+++ .32324-linux-2.6.0.updated/arch/i386/kernel/vsyscall.lds 1970-01-01 10:00:00.000000000 +1000
@@ -1,67 +0,0 @@
-/*
- * Linker script for vsyscall DSO. The vsyscall page is an ELF shared
- * object prelinked to its virtual address, and with only one read-only
- * segment (that fits in one page). This script controls its layout.
- */
-
-/* This must match <asm/fixmap.h>. */
-VSYSCALL_BASE = 0xffffe000;
-
-SECTIONS
-{
- . = VSYSCALL_BASE + SIZEOF_HEADERS;
-
- .hash : { *(.hash) } :text
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
-
- /* This linker script is used both with -r and with -shared.
- For the layouts to match, we need to skip more than enough
- space for the dynamic symbol table et al. If this amount
- is insufficient, ld -shared will barf. Just increase it here. */
- . = VSYSCALL_BASE + 0x400;
-
- .text : { *(.text) } :text =0x90909090
-
- .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
- .eh_frame : { KEEP (*(.eh_frame)) } :text
- .dynamic : { *(.dynamic) } :text :dynamic
- .useless : {
- *(.got.plt) *(.got)
- *(.data .data.* .gnu.linkonce.d.*)
- *(.dynbss)
- *(.bss .bss.* .gnu.linkonce.b.*)
- } :text
-}
-
-/*
- * We must supply the ELF program headers explicitly to get just one
- * PT_LOAD segment, and set the flags explicitly to make segments read-only.
- */
-PHDRS
-{
- text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
- dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
- eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
-}
-
-/*
- * This controls what symbols we export from the DSO.
- */
-VERSION
-{
- LINUX_2.5 {
- global:
- __kernel_vsyscall;
- __kernel_sigreturn;
- __kernel_rt_sigreturn;
-
- local: *;
- };
-}
-
-/* The ELF entry point can be used to set the AT_SYSINFO value. */
-ENTRY(__kernel_vsyscall);
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/arch/i386/kernel/vsyscall.lds.S .32324-linux-2.6.0.updated/arch/i386/kernel/vsyscall.lds.S
--- .32324-linux-2.6.0/arch/i386/kernel/vsyscall.lds.S 1970-01-01 10:00:00.000000000 +1000
+++ .32324-linux-2.6.0.updated/arch/i386/kernel/vsyscall.lds.S 2003-12-26 16:46:49.000000000 +1100
@@ -0,0 +1,67 @@
+/*
+ * Linker script for vsyscall DSO. The vsyscall page is an ELF shared
+ * object prelinked to its virtual address, and with only one read-only
+ * segment (that fits in one page). This script controls its layout.
+ */
+#include <asm/fixmap.h>
+
+VSYSCALL_BASE = __FIXADDR_TOP - 0x1000;
+
+SECTIONS
+{
+ . = VSYSCALL_BASE + SIZEOF_HEADERS;
+
+ .hash : { *(.hash) } :text
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+
+ /* This linker script is used both with -r and with -shared.
+ For the layouts to match, we need to skip more than enough
+ space for the dynamic symbol table et al. If this amount
+ is insufficient, ld -shared will barf. Just increase it here. */
+ . = VSYSCALL_BASE + 0x400;
+
+ .text : { *(.text) } :text =0x90909090
+
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+ .dynamic : { *(.dynamic) } :text :dynamic
+ .useless : {
+ *(.got.plt) *(.got)
+ *(.data .data.* .gnu.linkonce.d.*)
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ } :text
+}
+
+/*
+ * We must supply the ELF program headers explicitly to get just one
+ * PT_LOAD segment, and set the flags explicitly to make segments read-only.
+ */
+PHDRS
+{
+ text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+ eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+ LINUX_2.5 {
+ global:
+ __kernel_vsyscall;
+ __kernel_sigreturn;
+ __kernel_rt_sigreturn;
+
+ local: *;
+ };
+}
+
+/* The ELF entry point can be used to set the AT_SYSINFO value. */
+ENTRY(__kernel_vsyscall);
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/include/asm-i386/fixmap.h .32324-linux-2.6.0.updated/include/asm-i386/fixmap.h
--- .32324-linux-2.6.0/include/asm-i386/fixmap.h 2003-09-22 10:09:12.000000000 +1000
+++ .32324-linux-2.6.0.updated/include/asm-i386/fixmap.h 2003-12-26 16:46:49.000000000 +1100
@@ -14,6 +14,19 @@
#define _ASM_FIXMAP_H
#include <linux/config.h>
+
+/* used by vmalloc.c, vsyscall.lds.S.
+ *
+ * Leave one empty page between vmalloc'ed areas and
+ * the start of the fixmap.
+ */
+#ifdef CONFIG_QEMU
+#define __FIXADDR_TOP 0xa7fff000
+#else
+#define __FIXADDR_TOP 0xfffff000
+#endif
+
+#ifndef __ASSEMBLY__
#include <linux/kernel.h>
#include <asm/acpi.h>
#include <asm/apicdef.h>
@@ -94,13 +107,8 @@ extern void __set_fixmap (enum fixed_add
#define clear_fixmap(idx) \
__set_fixmap(idx, 0, __pgprot(0))
-/*
- * used by vmalloc.c.
- *
- * Leave one empty page between vmalloc'ed areas and
- * the start of the fixmap.
- */
-#define FIXADDR_TOP (0xfffff000UL)
+#define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP)
+
#define __FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT)
#define FIXADDR_START (FIXADDR_TOP - __FIXADDR_SIZE)
@@ -145,4 +153,5 @@ static inline unsigned long virt_to_fix(
return __virt_to_fix(vaddr);
}
+#endif /* !__ASSEMBLY__ */
#endif
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/include/asm-i386/page.h .32324-linux-2.6.0.updated/include/asm-i386/page.h
--- .32324-linux-2.6.0/include/asm-i386/page.h 2003-09-22 10:06:42.000000000 +1000
+++ .32324-linux-2.6.0.updated/include/asm-i386/page.h 2003-12-26 16:46:49.000000000 +1100
@@ -10,10 +10,10 @@
#define LARGE_PAGE_SIZE (1UL << PMD_SHIFT)
#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-
#include <linux/config.h>
+#ifndef __ASSEMBLY__
+
#ifdef CONFIG_X86_USE_3DNOW
#include <asm/mmx.h>
@@ -115,12 +115,19 @@ static __inline__ int get_order(unsigned
#endif /* __ASSEMBLY__ */
#ifdef __ASSEMBLY__
+#ifdef CONFIG_QEMU
+#define __PAGE_OFFSET (0x90000000)
+#else
#define __PAGE_OFFSET (0xC0000000)
+#endif /* QEMU */
+#else
+#ifdef CONFIG_QEMU
+#define __PAGE_OFFSET (0x90000000UL)
#else
#define __PAGE_OFFSET (0xC0000000UL)
+#endif /* QEMU */
#endif
-
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
#define VMALLOC_RESERVE ((unsigned long)__VMALLOC_RESERVE)
#define MAXMEM (-__PAGE_OFFSET-__VMALLOC_RESERVE)
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .32324-linux-2.6.0/include/asm-i386/param.h .32324-linux-2.6.0.updated/include/asm-i386/param.h
--- .32324-linux-2.6.0/include/asm-i386/param.h 2003-09-21 17:26:06.000000000 +1000
+++ .32324-linux-2.6.0.updated/include/asm-i386/param.h 2003-12-26 16:46:49.000000000 +1100
@@ -2,7 +2,12 @@
#define _ASMi386_PARAM_H
#ifdef __KERNEL__
-# define HZ 1000 /* Internal kernel timer frequency */
+# include <linux/config.h>
+# ifdef CONFIG_QEMU
+# define HZ 100
+# else
+# define HZ 1000 /* Internal kernel timer frequency */
+# endif
# define USER_HZ 100 /* .. some user interfaces are in "ticks" */
# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
#endif

View File

@@ -26,3 +26,5 @@ struct target_pt_regs {
#define ARM_ORIG_r0 uregs[17]
#define ARM_SYSCALL_BASE 0x900000
#define ARM_NR_cacheflush (ARM_SYSCALL_BASE + 0xf0000 + 2)

261
linux-user/arm/syscall_nr.h Normal file
View File

@@ -0,0 +1,261 @@
/*
* This file contains the system call numbers.
*/
#define TARGET_NR_restart_syscall ( 0)
#define TARGET_NR_exit ( 1)
#define TARGET_NR_fork ( 2)
#define TARGET_NR_read ( 3)
#define TARGET_NR_write ( 4)
#define TARGET_NR_open ( 5)
#define TARGET_NR_close ( 6)
#define TARGET_NR_waitpid ( 7) /* removed */
#define TARGET_NR_creat ( 8)
#define TARGET_NR_link ( 9)
#define TARGET_NR_unlink ( 10)
#define TARGET_NR_execve ( 11)
#define TARGET_NR_chdir ( 12)
#define TARGET_NR_time ( 13)
#define TARGET_NR_mknod ( 14)
#define TARGET_NR_chmod ( 15)
#define TARGET_NR_lchown ( 16)
#define TARGET_NR_break ( 17) /* removed */
/* 18 was sys_stat */
#define TARGET_NR_lseek ( 19)
#define TARGET_NR_getpid ( 20)
#define TARGET_NR_mount ( 21)
#define TARGET_NR_umount ( 22)
#define TARGET_NR_setuid ( 23)
#define TARGET_NR_getuid ( 24)
#define TARGET_NR_stime ( 25)
#define TARGET_NR_ptrace ( 26)
#define TARGET_NR_alarm ( 27)
#define TARGET_NR_pause ( 29)
#define TARGET_NR_utime ( 30)
#define TARGET_NR_stty ( 31) /* removed */
#define TARGET_NR_gtty ( 32) /* removed */
#define TARGET_NR_access ( 33)
#define TARGET_NR_nice ( 34)
#define TARGET_NR_ftime ( 35) /* removed */
#define TARGET_NR_sync ( 36)
#define TARGET_NR_kill ( 37)
#define TARGET_NR_rename ( 38)
#define TARGET_NR_mkdir ( 39)
#define TARGET_NR_rmdir ( 40)
#define TARGET_NR_dup ( 41)
#define TARGET_NR_pipe ( 42)
#define TARGET_NR_times ( 43)
#define TARGET_NR_prof ( 44) /* removed */
#define TARGET_NR_brk ( 45)
#define TARGET_NR_setgid ( 46)
#define TARGET_NR_getgid ( 47)
#define TARGET_NR_signal ( 48) /* removed */
#define TARGET_NR_geteuid ( 49)
#define TARGET_NR_getegid ( 50)
#define TARGET_NR_acct ( 51)
#define TARGET_NR_umount2 ( 52)
#define TARGET_NR_lock ( 53) /* removed */
#define TARGET_NR_ioctl ( 54)
#define TARGET_NR_fcntl ( 55)
#define TARGET_NR_mpx ( 56) /* removed */
#define TARGET_NR_setpgid ( 57)
#define TARGET_NR_ulimit ( 58) /* removed */
/* 59 was sys_olduname */
#define TARGET_NR_umask ( 60)
#define TARGET_NR_chroot ( 61)
#define TARGET_NR_ustat ( 62)
#define TARGET_NR_dup2 ( 63)
#define TARGET_NR_getppid ( 64)
#define TARGET_NR_getpgrp ( 65)
#define TARGET_NR_setsid ( 66)
#define TARGET_NR_sigaction ( 67)
#define TARGET_NR_sgetmask ( 68) /* removed */
#define TARGET_NR_ssetmask ( 69) /* removed */
#define TARGET_NR_setreuid ( 70)
#define TARGET_NR_setregid ( 71)
#define TARGET_NR_sigsuspend ( 72)
#define TARGET_NR_sigpending ( 73)
#define TARGET_NR_sethostname ( 74)
#define TARGET_NR_setrlimit ( 75)
#define TARGET_NR_getrlimit ( 76) /* Back compat 2GB limited rlimit */
#define TARGET_NR_getrusage ( 77)
#define TARGET_NR_gettimeofday ( 78)
#define TARGET_NR_settimeofday ( 79)
#define TARGET_NR_getgroups ( 80)
#define TARGET_NR_setgroups ( 81)
#define TARGET_NR_select ( 82)
#define TARGET_NR_symlink ( 83)
/* 84 was sys_lstat */
#define TARGET_NR_readlink ( 85)
#define TARGET_NR_uselib ( 86)
#define TARGET_NR_swapon ( 87)
#define TARGET_NR_reboot ( 88)
#define TARGET_NR_readdir ( 89)
#define TARGET_NR_mmap ( 90)
#define TARGET_NR_munmap ( 91)
#define TARGET_NR_truncate ( 92)
#define TARGET_NR_ftruncate ( 93)
#define TARGET_NR_fchmod ( 94)
#define TARGET_NR_fchown ( 95)
#define TARGET_NR_getpriority ( 96)
#define TARGET_NR_setpriority ( 97)
#define TARGET_NR_profil ( 98) /* removed */
#define TARGET_NR_statfs ( 99)
#define TARGET_NR_fstatfs (100)
#define TARGET_NR_ioperm (101)
#define TARGET_NR_socketcall (102)
#define TARGET_NR_syslog (103)
#define TARGET_NR_setitimer (104)
#define TARGET_NR_getitimer (105)
#define TARGET_NR_stat (106)
#define TARGET_NR_lstat (107)
#define TARGET_NR_fstat (108)
/* 109 was sys_uname */
/* 110 was sys_iopl */
#define TARGET_NR_vhangup (111)
#define TARGET_NR_idle (112)
#define TARGET_NR_syscall (113) /* syscall to call a syscall! */
#define TARGET_NR_wait4 (114)
#define TARGET_NR_swapoff (115)
#define TARGET_NR_sysinfo (116)
#define TARGET_NR_ipc (117)
#define TARGET_NR_fsync (118)
#define TARGET_NR_sigreturn (119)
#define TARGET_NR_clone (120)
#define TARGET_NR_setdomainname (121)
#define TARGET_NR_uname (122)
#define TARGET_NR_modify_ldt (123)
#define TARGET_NR_adjtimex (124)
#define TARGET_NR_mprotect (125)
#define TARGET_NR_sigprocmask (126)
#define TARGET_NR_create_module (127) /* removed */
#define TARGET_NR_init_module (128)
#define TARGET_NR_delete_module (129)
#define TARGET_NR_get_kernel_syms (130) /* removed */
#define TARGET_NR_quotactl (131)
#define TARGET_NR_getpgid (132)
#define TARGET_NR_fchdir (133)
#define TARGET_NR_bdflush (134)
#define TARGET_NR_sysfs (135)
#define TARGET_NR_personality (136)
#define TARGET_NR_afs_syscall (137) /* Syscall for Andrew File System */
#define TARGET_NR_setfsuid (138)
#define TARGET_NR_setfsgid (139)
#define TARGET_NR__llseek (140)
#define TARGET_NR_getdents (141)
#define TARGET_NR__newselect (142)
#define TARGET_NR_flock (143)
#define TARGET_NR_msync (144)
#define TARGET_NR_readv (145)
#define TARGET_NR_writev (146)
#define TARGET_NR_getsid (147)
#define TARGET_NR_fdatasync (148)
#define TARGET_NR__sysctl (149)
#define TARGET_NR_mlock (150)
#define TARGET_NR_munlock (151)
#define TARGET_NR_mlockall (152)
#define TARGET_NR_munlockall (153)
#define TARGET_NR_sched_setparam (154)
#define TARGET_NR_sched_getparam (155)
#define TARGET_NR_sched_setscheduler (156)
#define TARGET_NR_sched_getscheduler (157)
#define TARGET_NR_sched_yield (158)
#define TARGET_NR_sched_get_priority_max (159)
#define TARGET_NR_sched_get_priority_min (160)
#define TARGET_NR_sched_rr_get_interval (161)
#define TARGET_NR_nanosleep (162)
#define TARGET_NR_mremap (163)
#define TARGET_NR_setresuid (164)
#define TARGET_NR_getresuid (165)
#define TARGET_NR_vm86 (166) /* removed */
#define TARGET_NR_query_module (167) /* removed */
#define TARGET_NR_poll (168)
#define TARGET_NR_nfsservctl (169)
#define TARGET_NR_setresgid (170)
#define TARGET_NR_getresgid (171)
#define TARGET_NR_prctl (172)
#define TARGET_NR_rt_sigreturn (173)
#define TARGET_NR_rt_sigaction (174)
#define TARGET_NR_rt_sigprocmask (175)
#define TARGET_NR_rt_sigpending (176)
#define TARGET_NR_rt_sigtimedwait (177)
#define TARGET_NR_rt_sigqueueinfo (178)
#define TARGET_NR_rt_sigsuspend (179)
#define TARGET_NR_pread (180)
#define TARGET_NR_pwrite (181)
#define TARGET_NR_chown (182)
#define TARGET_NR_getcwd (183)
#define TARGET_NR_capget (184)
#define TARGET_NR_capset (185)
#define TARGET_NR_sigaltstack (186)
#define TARGET_NR_sendfile (187)
/* 188 reserved */
/* 189 reserved */
#define TARGET_NR_vfork (190)
#define TARGET_NR_ugetrlimit (191) /* SuS compliant getrlimit */
#define TARGET_NR_mmap2 (192)
#define TARGET_NR_truncate64 (193)
#define TARGET_NR_ftruncate64 (194)
#define TARGET_NR_stat64 (195)
#define TARGET_NR_lstat64 (196)
#define TARGET_NR_fstat64 (197)
#define TARGET_NR_lchown32 (198)
#define TARGET_NR_getuid32 (199)
#define TARGET_NR_getgid32 (200)
#define TARGET_NR_geteuid32 (201)
#define TARGET_NR_getegid32 (202)
#define TARGET_NR_setreuid32 (203)
#define TARGET_NR_setregid32 (204)
#define TARGET_NR_getgroups32 (205)
#define TARGET_NR_setgroups32 (206)
#define TARGET_NR_fchown32 (207)
#define TARGET_NR_setresuid32 (208)
#define TARGET_NR_getresuid32 (209)
#define TARGET_NR_setresgid32 (210)
#define TARGET_NR_getresgid32 (211)
#define TARGET_NR_chown32 (212)
#define TARGET_NR_setuid32 (213)
#define TARGET_NR_setgid32 (214)
#define TARGET_NR_setfsuid32 (215)
#define TARGET_NR_setfsgid32 (216)
#define TARGET_NR_getdents64 (217)
#define TARGET_NR_pivot_root (218)
#define TARGET_NR_mincore (219)
#define TARGET_NR_madvise (220)
#define TARGET_NR_fcntl64 (221)
/* 222 for tux */
/* 223 is unused */
#define TARGET_NR_gettid (224)
#define TARGET_NR_readahead (225)
#define TARGET_NR_setxattr (226)
#define TARGET_NR_lsetxattr (227)
#define TARGET_NR_fsetxattr (228)
#define TARGET_NR_getxattr (229)
#define TARGET_NR_lgetxattr (230)
#define TARGET_NR_fgetxattr (231)
#define TARGET_NR_listxattr (232)
#define TARGET_NR_llistxattr (233)
#define TARGET_NR_flistxattr (234)
#define TARGET_NR_removexattr (235)
#define TARGET_NR_lremovexattr (236)
#define TARGET_NR_fremovexattr (237)
#define TARGET_NR_tkill (238)
#define TARGET_NR_sendfile64 (239)
#define TARGET_NR_futex (240)
#define TARGET_NR_sched_setaffinity (241)
#define TARGET_NR_sched_getaffinity (242)
#define TARGET_NR_io_setup (243)
#define TARGET_NR_io_destroy (244)
#define TARGET_NR_io_getevents (245)
#define TARGET_NR_io_submit (246)
#define TARGET_NR_io_cancel (247)
#define TARGET_NR_exit_group (248)
#define TARGET_NR_lookup_dcookie (249)
#define TARGET_NR_epoll_create (250)
#define TARGET_NR_epoll_ctl (251)
#define TARGET_NR_epoll_wait (252)
#define TARGET_NR_remap_file_pages (253)
/* 254 for set_thread_area */
/* 255 for get_thread_area */
/* 256 for set_tid_address */

215
linux-user/arm/termbits.h Normal file
View File

@@ -0,0 +1,215 @@
/* from asm/termbits.h */
/* NOTE: exactly the same as i386 */
#define TARGET_NCCS 19
struct target_termios {
unsigned int c_iflag; /* input mode flags */
unsigned int c_oflag; /* output mode flags */
unsigned int c_cflag; /* control mode flags */
unsigned int c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[TARGET_NCCS]; /* control characters */
};
/* c_iflag bits */
#define TARGET_IGNBRK 0000001
#define TARGET_BRKINT 0000002
#define TARGET_IGNPAR 0000004
#define TARGET_PARMRK 0000010
#define TARGET_INPCK 0000020
#define TARGET_ISTRIP 0000040
#define TARGET_INLCR 0000100
#define TARGET_IGNCR 0000200
#define TARGET_ICRNL 0000400
#define TARGET_IUCLC 0001000
#define TARGET_IXON 0002000
#define TARGET_IXANY 0004000
#define TARGET_IXOFF 0010000
#define TARGET_IMAXBEL 0020000
/* c_oflag bits */
#define TARGET_OPOST 0000001
#define TARGET_OLCUC 0000002
#define TARGET_ONLCR 0000004
#define TARGET_OCRNL 0000010
#define TARGET_ONOCR 0000020
#define TARGET_ONLRET 0000040
#define TARGET_OFILL 0000100
#define TARGET_OFDEL 0000200
#define TARGET_NLDLY 0000400
#define TARGET_NL0 0000000
#define TARGET_NL1 0000400
#define TARGET_CRDLY 0003000
#define TARGET_CR0 0000000
#define TARGET_CR1 0001000
#define TARGET_CR2 0002000
#define TARGET_CR3 0003000
#define TARGET_TABDLY 0014000
#define TARGET_TAB0 0000000
#define TARGET_TAB1 0004000
#define TARGET_TAB2 0010000
#define TARGET_TAB3 0014000
#define TARGET_XTABS 0014000
#define TARGET_BSDLY 0020000
#define TARGET_BS0 0000000
#define TARGET_BS1 0020000
#define TARGET_VTDLY 0040000
#define TARGET_VT0 0000000
#define TARGET_VT1 0040000
#define TARGET_FFDLY 0100000
#define TARGET_FF0 0000000
#define TARGET_FF1 0100000
/* c_cflag bit meaning */
#define TARGET_CBAUD 0010017
#define TARGET_B0 0000000 /* hang up */
#define TARGET_B50 0000001
#define TARGET_B75 0000002
#define TARGET_B110 0000003
#define TARGET_B134 0000004
#define TARGET_B150 0000005
#define TARGET_B200 0000006
#define TARGET_B300 0000007
#define TARGET_B600 0000010
#define TARGET_B1200 0000011
#define TARGET_B1800 0000012
#define TARGET_B2400 0000013
#define TARGET_B4800 0000014
#define TARGET_B9600 0000015
#define TARGET_B19200 0000016
#define TARGET_B38400 0000017
#define TARGET_EXTA B19200
#define TARGET_EXTB B38400
#define TARGET_CSIZE 0000060
#define TARGET_CS5 0000000
#define TARGET_CS6 0000020
#define TARGET_CS7 0000040
#define TARGET_CS8 0000060
#define TARGET_CSTOPB 0000100
#define TARGET_CREAD 0000200
#define TARGET_PARENB 0000400
#define TARGET_PARODD 0001000
#define TARGET_HUPCL 0002000
#define TARGET_CLOCAL 0004000
#define TARGET_CBAUDEX 0010000
#define TARGET_B57600 0010001
#define TARGET_B115200 0010002
#define TARGET_B230400 0010003
#define TARGET_B460800 0010004
#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */
#define TARGET_CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
#define TARGET_ISIG 0000001
#define TARGET_ICANON 0000002
#define TARGET_XCASE 0000004
#define TARGET_ECHO 0000010
#define TARGET_ECHOE 0000020
#define TARGET_ECHOK 0000040
#define TARGET_ECHONL 0000100
#define TARGET_NOFLSH 0000200
#define TARGET_TOSTOP 0000400
#define TARGET_ECHOCTL 0001000
#define TARGET_ECHOPRT 0002000
#define TARGET_ECHOKE 0004000
#define TARGET_FLUSHO 0010000
#define TARGET_PENDIN 0040000
#define TARGET_IEXTEN 0100000
/* c_cc character offsets */
#define TARGET_VINTR 0
#define TARGET_VQUIT 1
#define TARGET_VERASE 2
#define TARGET_VKILL 3
#define TARGET_VEOF 4
#define TARGET_VTIME 5
#define TARGET_VMIN 6
#define TARGET_VSWTC 7
#define TARGET_VSTART 8
#define TARGET_VSTOP 9
#define TARGET_VSUSP 10
#define TARGET_VEOL 11
#define TARGET_VREPRINT 12
#define TARGET_VDISCARD 13
#define TARGET_VWERASE 14
#define TARGET_VLNEXT 15
#define TARGET_VEOL2 16
/* ioctls */
#define TARGET_TCGETS 0x5401
#define TARGET_TCSETS 0x5402
#define TARGET_TCSETSW 0x5403
#define TARGET_TCSETSF 0x5404
#define TARGET_TCGETA 0x5405
#define TARGET_TCSETA 0x5406
#define TARGET_TCSETAW 0x5407
#define TARGET_TCSETAF 0x5408
#define TARGET_TCSBRK 0x5409
#define TARGET_TCXONC 0x540A
#define TARGET_TCFLSH 0x540B
#define TARGET_TIOCEXCL 0x540C
#define TARGET_TIOCNXCL 0x540D
#define TARGET_TIOCSCTTY 0x540E
#define TARGET_TIOCGPGRP 0x540F
#define TARGET_TIOCSPGRP 0x5410
#define TARGET_TIOCOUTQ 0x5411
#define TARGET_TIOCSTI 0x5412
#define TARGET_TIOCGWINSZ 0x5413
#define TARGET_TIOCSWINSZ 0x5414
#define TARGET_TIOCMGET 0x5415
#define TARGET_TIOCMBIS 0x5416
#define TARGET_TIOCMBIC 0x5417
#define TARGET_TIOCMSET 0x5418
#define TARGET_TIOCGSOFTCAR 0x5419
#define TARGET_TIOCSSOFTCAR 0x541A
#define TARGET_FIONREAD 0x541B
#define TARGET_TIOCINQ TARGET_FIONREAD
#define TARGET_TIOCLINUX 0x541C
#define TARGET_TIOCCONS 0x541D
#define TARGET_TIOCGSERIAL 0x541E
#define TARGET_TIOCSSERIAL 0x541F
#define TARGET_TIOCPKT 0x5420
#define TARGET_FIONBIO 0x5421
#define TARGET_TIOCNOTTY 0x5422
#define TARGET_TIOCSETD 0x5423
#define TARGET_TIOCGETD 0x5424
#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */
#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */
#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */
#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */
#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */
#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define TARGET_FIOCLEX 0x5451
#define TARGET_FIOASYNC 0x5452
#define TARGET_TIOCSERCONFIG 0x5453
#define TARGET_TIOCSERGWILD 0x5454
#define TARGET_TIOCSERSWILD 0x5455
#define TARGET_TIOCGLCKTRMIOS 0x5456
#define TARGET_TIOCSLCKTRMIOS 0x5457
#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
/* Used for packet mode */
#define TARGET_TIOCPKT_DATA 0
#define TARGET_TIOCPKT_FLUSHREAD 1
#define TARGET_TIOCPKT_FLUSHWRITE 2
#define TARGET_TIOCPKT_STOP 4
#define TARGET_TIOCPKT_START 8
#define TARGET_TIOCPKT_NOSTOP 16
#define TARGET_TIOCPKT_DOSTOP 32
#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@@ -13,6 +13,16 @@
#include "qemu.h"
#include "disas.h"
/* this flag is uneffective under linux too, should be deleted */
#ifndef MAP_DENYWRITE
#define MAP_DENYWRITE 0
#endif
/* should probably go in elf.h */
#ifndef ELIBBAD
#define ELIBBAD 80
#endif
#ifdef TARGET_I386
#define ELF_START_MMAP 0x80000000
@@ -83,6 +93,103 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#endif
#ifdef TARGET_SPARC
#define ELF_START_MMAP 0x80000000
#define elf_check_arch(x) ( (x) == EM_SPARC )
#define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2MSB
#define ELF_ARCH EM_SPARC
/*XXX*/
#define ELF_PLAT_INIT(_r)
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
regs->psr = 0;
regs->pc = infop->entry;
regs->npc = regs->pc + 4;
regs->y = 0;
regs->u_regs[14] = infop->start_stack - 16 * 4;
}
#endif
#ifdef TARGET_PPC
#define ELF_START_MMAP 0x80000000
#define elf_check_arch(x) ( (x) == EM_PPC )
#define ELF_CLASS ELFCLASS32
#ifdef TARGET_WORDS_BIGENDIAN
#define ELF_DATA ELFDATA2MSB
#else
#define ELF_DATA ELFDATA2LSB
#endif
#define ELF_ARCH EM_PPC
/* Note that isn't exactly what regular kernel does
* but this is what the ABI wants and is needed to allow
* execution of PPC BSD programs.
*/
#define ELF_PLAT_INIT(_r) \
do { \
target_ulong *pos = (target_ulong *)bprm->p, tmp = 1; \
_r->gpr[3] = bprm->argc; \
_r->gpr[4] = (unsigned long)++pos; \
for (; tmp != 0; pos++) \
tmp = *pos; \
_r->gpr[5] = (unsigned long)pos; \
} while (0)
/*
* We need to put in some extra aux table entries to tell glibc what
* the cache block size is, so it can use the dcbz instruction safely.
*/
#define AT_DCACHEBSIZE 19
#define AT_ICACHEBSIZE 20
#define AT_UCACHEBSIZE 21
/* A special ignored type value for PPC, for glibc compatibility. */
#define AT_IGNOREPPC 22
/*
* The requirements here are:
* - keep the final alignment of sp (sp & 0xf)
* - make sure the 32-bit value at the first 16 byte aligned position of
* AUXV is greater than 16 for glibc compatibility.
* AT_IGNOREPPC is used for that.
* - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
* even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
*/
#define DLINFO_ARCH_ITEMS 3
#define ARCH_DLINFO \
do { \
sp -= DLINFO_ARCH_ITEMS * 2; \
NEW_AUX_ENT(0, AT_DCACHEBSIZE, 0x20); \
NEW_AUX_ENT(1, AT_ICACHEBSIZE, 0x20); \
NEW_AUX_ENT(2, AT_UCACHEBSIZE, 0); \
/* \
* Now handle glibc compatibility. \
*/ \
sp -= 2*2; \
NEW_AUX_ENT(0, AT_IGNOREPPC, AT_IGNOREPPC); \
NEW_AUX_ENT(1, AT_IGNOREPPC, AT_IGNOREPPC); \
} while (0)
static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
{
_regs->msr = 1 << MSR_PR; /* Set user mode */
_regs->gpr[1] = infop->start_stack;
_regs->nip = infop->entry;
}
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
#endif
#include "elf.h"
/*
@@ -164,21 +271,13 @@ struct exec
#define INTERPRETER_AOUT 1
#define INTERPRETER_ELF 2
#define DLINFO_ITEMS 12
#define put_user(x,ptr) (void)(*(ptr) = (typeof(*ptr))(x))
#define get_user(ptr) (typeof(*ptr))(*(ptr))
#define DLINFO_ITEMS 11
static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
{
memcpy(to, from, n);
}
static inline void memcpy_tofs(void * to, const void * from, unsigned long n)
{
memcpy(to, from, n);
}
extern unsigned long x86_stack_size;
static int load_aout_interp(void * exptr, int interp_fd);
@@ -243,7 +342,7 @@ static void * get_free_page(void)
/* User-space version of kernel get_free_page. Returns a page-aligned
* page-sized chunk of memory.
*/
retval = (void *)target_mmap(0, host_page_size, PROT_READ|PROT_WRITE,
retval = (void *)target_mmap(0, qemu_host_page_size, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if((long)retval == -1) {
@@ -257,7 +356,7 @@ static void * get_free_page(void)
static void free_page(void * pageaddr)
{
target_munmap((unsigned long)pageaddr, host_page_size);
target_munmap((unsigned long)pageaddr, qemu_host_page_size);
}
/*
@@ -276,11 +375,13 @@ static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
return 0; /* bullet-proofing */
}
while (argc-- > 0) {
if (!(tmp1 = tmp = get_user(argv+argc))) {
tmp = argv[argc];
if (!tmp) {
fprintf(stderr, "VFS: argc is wrong");
exit(-1);
}
while (get_user(tmp++));
tmp1 = tmp;
while (*tmp++);
len = tmp - tmp1;
if (p < len) { /* this shouldn't happen - 128kB */
return 0;
@@ -289,14 +390,16 @@ static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
--p; --tmp; --len;
if (--offset < 0) {
offset = p % TARGET_PAGE_SIZE;
if (!(pag = (char *) page[p/TARGET_PAGE_SIZE]) &&
!(pag = (char *) page[p/TARGET_PAGE_SIZE] =
(unsigned long *) get_free_page())) {
return 0;
pag = (char *) page[p/TARGET_PAGE_SIZE];
if (!pag) {
pag = (char *)get_free_page();
page[p/TARGET_PAGE_SIZE] = (unsigned long)pag;
if (!pag)
return 0;
}
}
if (len == 0 || offset == 0) {
*(pag + offset) = get_user(tmp);
*(pag + offset) = *tmp;
}
else {
int bytes_to_copy = (len > offset) ? offset : len;
@@ -409,7 +512,7 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
error = target_mmap(0,
size + host_page_size,
size + qemu_host_page_size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
@@ -418,7 +521,7 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
exit(-1);
}
/* we reserve one extra page at the top of the stack as guard */
target_mprotect(error + size, host_page_size, PROT_NONE);
target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
p += stack_base;
@@ -456,20 +559,34 @@ static void set_brk(unsigned long start, unsigned long end)
}
/* We need to explicitly zero any fractional pages
after the data section (i.e. bss). This would
contain the junk from the file that should not
be in memory */
/* We need to explicitly zero any fractional pages after the data
section (i.e. bss). This would contain the junk from the file that
should not be in memory. */
static void padzero(unsigned long elf_bss)
{
unsigned long nbyte;
char * fpnt;
nbyte = elf_bss & (host_page_size-1); /* was TARGET_PAGE_SIZE - JRP */
/* XXX: this is really a hack : if the real host page size is
smaller than the target page size, some pages after the end
of the file may not be mapped. A better fix would be to
patch target_mmap(), but it is more complicated as the file
size must be known */
if (qemu_real_host_page_size < qemu_host_page_size) {
unsigned long end_addr, end_addr1;
end_addr1 = (elf_bss + qemu_real_host_page_size - 1) &
~(qemu_real_host_page_size - 1);
end_addr = HOST_PAGE_ALIGN(elf_bss);
if (end_addr1 < end_addr) {
mmap((void *)end_addr1, end_addr - end_addr1,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
}
}
nbyte = elf_bss & (qemu_host_page_size-1);
if (nbyte) {
nbyte = host_page_size - nbyte;
nbyte = qemu_host_page_size - nbyte;
fpnt = (char *) elf_bss;
do {
*fpnt++ = 0;
@@ -484,53 +601,77 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc,
unsigned long interp_load_addr, int ibcs,
struct image_info *info)
{
target_ulong *argv, *envp, *dlinfo;
target_ulong *sp;
target_ulong *argv, *envp;
target_ulong *sp, *csp;
int v;
/*
* Force 16 byte alignment here for generality.
*/
/*
* Force 16 byte _final_ alignment here for generality.
*/
sp = (unsigned int *) (~15UL & (unsigned long) p);
sp -= DLINFO_ITEMS*2;
dlinfo = sp;
csp = sp;
csp -= (DLINFO_ITEMS + 1) * 2;
#ifdef DLINFO_ARCH_ITEMS
csp -= DLINFO_ARCH_ITEMS*2;
#endif
csp -= envc+1;
csp -= argc+1;
csp -= (!ibcs ? 3 : 1); /* argc itself */
if ((unsigned long)csp & 15UL)
sp -= ((unsigned long)csp & 15UL) / sizeof(*sp);
#define NEW_AUX_ENT(nr, id, val) \
put_user (id, sp + (nr * 2)); \
put_user (val, sp + (nr * 2 + 1))
sp -= 2;
NEW_AUX_ENT (0, AT_NULL, 0);
sp -= DLINFO_ITEMS*2;
NEW_AUX_ENT( 0, AT_PHDR, (target_ulong)(load_addr + exec->e_phoff));
NEW_AUX_ENT( 1, AT_PHENT, (target_ulong)(sizeof (struct elf_phdr)));
NEW_AUX_ENT( 2, AT_PHNUM, (target_ulong)(exec->e_phnum));
NEW_AUX_ENT( 3, AT_PAGESZ, (target_ulong)(TARGET_PAGE_SIZE));
NEW_AUX_ENT( 4, AT_BASE, (target_ulong)(interp_load_addr));
NEW_AUX_ENT( 5, AT_FLAGS, (target_ulong)0);
NEW_AUX_ENT( 6, AT_ENTRY, load_bias + exec->e_entry);
NEW_AUX_ENT( 7, AT_UID, (target_ulong) getuid());
NEW_AUX_ENT( 8, AT_EUID, (target_ulong) geteuid());
NEW_AUX_ENT( 9, AT_GID, (target_ulong) getgid());
NEW_AUX_ENT(11, AT_EGID, (target_ulong) getegid());
#ifdef ARCH_DLINFO
/*
* ARCH_DLINFO must come last so platform specific code can enforce
* special alignment requirements on the AUXV if necessary (eg. PPC).
*/
ARCH_DLINFO;
#endif
#undef NEW_AUX_ENT
sp -= envc+1;
envp = sp;
sp -= argc+1;
argv = sp;
if (!ibcs) {
put_user(tswapl((target_ulong)envp),--sp);
put_user(tswapl((target_ulong)argv),--sp);
put_user((target_ulong)envp,--sp);
put_user((target_ulong)argv,--sp);
}
#define NEW_AUX_ENT(id, val) \
put_user (tswapl(id), dlinfo++); \
put_user (tswapl(val), dlinfo++)
NEW_AUX_ENT (AT_PHDR, (target_ulong)(load_addr + exec->e_phoff));
NEW_AUX_ENT (AT_PHENT, (target_ulong)(sizeof (struct elf_phdr)));
NEW_AUX_ENT (AT_PHNUM, (target_ulong)(exec->e_phnum));
NEW_AUX_ENT (AT_PAGESZ, (target_ulong)(TARGET_PAGE_SIZE));
NEW_AUX_ENT (AT_BASE, (target_ulong)(interp_load_addr));
NEW_AUX_ENT (AT_FLAGS, (target_ulong)0);
NEW_AUX_ENT (AT_ENTRY, load_bias + exec->e_entry);
NEW_AUX_ENT (AT_UID, (target_ulong) getuid());
NEW_AUX_ENT (AT_EUID, (target_ulong) geteuid());
NEW_AUX_ENT (AT_GID, (target_ulong) getgid());
NEW_AUX_ENT (AT_EGID, (target_ulong) getegid());
NEW_AUX_ENT (AT_NULL, 0);
#undef NEW_AUX_ENT
put_user(tswapl(argc),--sp);
put_user(argc,--sp);
info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff);
while (argc-->0) {
put_user(tswapl((target_ulong)p),argv++);
while (get_user(p++)) /* nothing */ ;
put_user((target_ulong)p,argv++);
do {
get_user(v, p);
p++;
} while (v != 0);
}
put_user(0,argv);
info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff);
while (envc-->0) {
put_user(tswapl((target_ulong)p),envp++);
while (get_user(p++)) /* nothing */ ;
put_user((target_ulong)p,envp++);
do {
get_user(v, p);
p++;
} while (v != 0);
}
put_user(0,envp);
info->env_end = (unsigned int)((unsigned long)p & 0xffffffff);
@@ -680,7 +821,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
* bss page.
*/
padzero(elf_bss);
elf_bss = TARGET_ELF_PAGESTART(elf_bss + host_page_size - 1); /* What we have mapped so far */
elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */
/* Map the last of the bss segment */
if (last_bss > elf_bss) {
@@ -936,7 +1077,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
char * passed_p;
if (interpreter_type == INTERPRETER_AOUT) {
sprintf(passed_fileno, "%d", bprm->fd);
snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
passed_p = passed_fileno;
if (elf_interpreter) {
@@ -1121,7 +1262,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r
and some applications "depend" upon this behavior.
Since we do not have the power to recompile these, we
emulate the SVr4 behavior. Sigh. */
mapped_addr = target_mmap(0, host_page_size, PROT_READ | PROT_EXEC,
mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, -1, 0);
}
@@ -1154,14 +1295,9 @@ int elf_exec(const char * filename, char ** argv, char ** envp,
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
bprm.page[i] = 0;
retval = open(filename, O_RDONLY);
if (retval == -1) {
perror(filename);
exit(-1);
/* return retval; */
}
else {
bprm.fd = retval;
}
if (retval < 0)
return retval;
bprm.fd = retval;
bprm.filename = (char *)filename;
bprm.sh_bang = 0;
bprm.loader = 0;

View File

@@ -0,0 +1,273 @@
/*
* This file contains the system call numbers.
*/
#define TARGET_NR_restart_syscall 0
#define TARGET_NR_exit 1
#define TARGET_NR_fork 2
#define TARGET_NR_read 3
#define TARGET_NR_write 4
#define TARGET_NR_open 5
#define TARGET_NR_close 6
#define TARGET_NR_waitpid 7
#define TARGET_NR_creat 8
#define TARGET_NR_link 9
#define TARGET_NR_unlink 10
#define TARGET_NR_execve 11
#define TARGET_NR_chdir 12
#define TARGET_NR_time 13
#define TARGET_NR_mknod 14
#define TARGET_NR_chmod 15
#define TARGET_NR_lchown 16
#define TARGET_NR_break 17
#define TARGET_NR_oldstat 18
#define TARGET_NR_lseek 19
#define TARGET_NR_getpid 20
#define TARGET_NR_mount 21
#define TARGET_NR_umount 22
#define TARGET_NR_setuid 23
#define TARGET_NR_getuid 24
#define TARGET_NR_stime 25
#define TARGET_NR_ptrace 26
#define TARGET_NR_alarm 27
#define TARGET_NR_oldfstat 28
#define TARGET_NR_pause 29
#define TARGET_NR_utime 30
#define TARGET_NR_stty 31
#define TARGET_NR_gtty 32
#define TARGET_NR_access 33
#define TARGET_NR_nice 34
#define TARGET_NR_ftime 35
#define TARGET_NR_sync 36
#define TARGET_NR_kill 37
#define TARGET_NR_rename 38
#define TARGET_NR_mkdir 39
#define TARGET_NR_rmdir 40
#define TARGET_NR_dup 41
#define TARGET_NR_pipe 42
#define TARGET_NR_times 43
#define TARGET_NR_prof 44
#define TARGET_NR_brk 45
#define TARGET_NR_setgid 46
#define TARGET_NR_getgid 47
#define TARGET_NR_signal 48
#define TARGET_NR_geteuid 49
#define TARGET_NR_getegid 50
#define TARGET_NR_acct 51
#define TARGET_NR_umount2 52
#define TARGET_NR_lock 53
#define TARGET_NR_ioctl 54
#define TARGET_NR_fcntl 55
#define TARGET_NR_mpx 56
#define TARGET_NR_setpgid 57
#define TARGET_NR_ulimit 58
#define TARGET_NR_oldolduname 59
#define TARGET_NR_umask 60
#define TARGET_NR_chroot 61
#define TARGET_NR_ustat 62
#define TARGET_NR_dup2 63
#define TARGET_NR_getppid 64
#define TARGET_NR_getpgrp 65
#define TARGET_NR_setsid 66
#define TARGET_NR_sigaction 67
#define TARGET_NR_sgetmask 68
#define TARGET_NR_ssetmask 69
#define TARGET_NR_setreuid 70
#define TARGET_NR_setregid 71
#define TARGET_NR_sigsuspend 72
#define TARGET_NR_sigpending 73
#define TARGET_NR_sethostname 74
#define TARGET_NR_setrlimit 75
#define TARGET_NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
#define TARGET_NR_getrusage 77
#define TARGET_NR_gettimeofday 78
#define TARGET_NR_settimeofday 79
#define TARGET_NR_getgroups 80
#define TARGET_NR_setgroups 81
#define TARGET_NR_select 82
#define TARGET_NR_symlink 83
#define TARGET_NR_oldlstat 84
#define TARGET_NR_readlink 85
#define TARGET_NR_uselib 86
#define TARGET_NR_swapon 87
#define TARGET_NR_reboot 88
#define TARGET_NR_readdir 89
#define TARGET_NR_mmap 90
#define TARGET_NR_munmap 91
#define TARGET_NR_truncate 92
#define TARGET_NR_ftruncate 93
#define TARGET_NR_fchmod 94
#define TARGET_NR_fchown 95
#define TARGET_NR_getpriority 96
#define TARGET_NR_setpriority 97
#define TARGET_NR_profil 98
#define TARGET_NR_statfs 99
#define TARGET_NR_fstatfs 100
#define TARGET_NR_ioperm 101
#define TARGET_NR_socketcall 102
#define TARGET_NR_syslog 103
#define TARGET_NR_setitimer 104
#define TARGET_NR_getitimer 105
#define TARGET_NR_stat 106
#define TARGET_NR_lstat 107
#define TARGET_NR_fstat 108
#define TARGET_NR_olduname 109
#define TARGET_NR_iopl 110
#define TARGET_NR_vhangup 111
#define TARGET_NR_idle 112
#define TARGET_NR_vm86old 113
#define TARGET_NR_wait4 114
#define TARGET_NR_swapoff 115
#define TARGET_NR_sysinfo 116
#define TARGET_NR_ipc 117
#define TARGET_NR_fsync 118
#define TARGET_NR_sigreturn 119
#define TARGET_NR_clone 120
#define TARGET_NR_setdomainname 121
#define TARGET_NR_uname 122
#define TARGET_NR_modify_ldt 123
#define TARGET_NR_adjtimex 124
#define TARGET_NR_mprotect 125
#define TARGET_NR_sigprocmask 126
#define TARGET_NR_create_module 127
#define TARGET_NR_init_module 128
#define TARGET_NR_delete_module 129
#define TARGET_NR_get_kernel_syms 130
#define TARGET_NR_quotactl 131
#define TARGET_NR_getpgid 132
#define TARGET_NR_fchdir 133
#define TARGET_NR_bdflush 134
#define TARGET_NR_sysfs 135
#define TARGET_NR_personality 136
#define TARGET_NR_afs_syscall 137 /* Syscall for Andrew File System */
#define TARGET_NR_setfsuid 138
#define TARGET_NR_setfsgid 139
#define TARGET_NR__llseek 140
#define TARGET_NR_getdents 141
#define TARGET_NR__newselect 142
#define TARGET_NR_flock 143
#define TARGET_NR_msync 144
#define TARGET_NR_readv 145
#define TARGET_NR_writev 146
#define TARGET_NR_getsid 147
#define TARGET_NR_fdatasync 148
#define TARGET_NR__sysctl 149
#define TARGET_NR_mlock 150
#define TARGET_NR_munlock 151
#define TARGET_NR_mlockall 152
#define TARGET_NR_munlockall 153
#define TARGET_NR_sched_setparam 154
#define TARGET_NR_sched_getparam 155
#define TARGET_NR_sched_setscheduler 156
#define TARGET_NR_sched_getscheduler 157
#define TARGET_NR_sched_yield 158
#define TARGET_NR_sched_get_priority_max 159
#define TARGET_NR_sched_get_priority_min 160
#define TARGET_NR_sched_rr_get_interval 161
#define TARGET_NR_nanosleep 162
#define TARGET_NR_mremap 163
#define TARGET_NR_setresuid 164
#define TARGET_NR_getresuid 165
#define TARGET_NR_vm86 166
#define TARGET_NR_query_module 167
#define TARGET_NR_poll 168
#define TARGET_NR_nfsservctl 169
#define TARGET_NR_setresgid 170
#define TARGET_NR_getresgid 171
#define TARGET_NR_prctl 172
#define TARGET_NR_rt_sigreturn 173
#define TARGET_NR_rt_sigaction 174
#define TARGET_NR_rt_sigprocmask 175
#define TARGET_NR_rt_sigpending 176
#define TARGET_NR_rt_sigtimedwait 177
#define TARGET_NR_rt_sigqueueinfo 178
#define TARGET_NR_rt_sigsuspend 179
#define TARGET_NR_pread 180
#define TARGET_NR_pwrite 181
#define TARGET_NR_chown 182
#define TARGET_NR_getcwd 183
#define TARGET_NR_capget 184
#define TARGET_NR_capset 185
#define TARGET_NR_sigaltstack 186
#define TARGET_NR_sendfile 187
#define TARGET_NR_getpmsg 188 /* some people actually want streams */
#define TARGET_NR_putpmsg 189 /* some people actually want streams */
#define TARGET_NR_vfork 190
#define TARGET_NR_ugetrlimit 191 /* SuS compliant getrlimit */
#define TARGET_NR_mmap2 192
#define TARGET_NR_truncate64 193
#define TARGET_NR_ftruncate64 194
#define TARGET_NR_stat64 195
#define TARGET_NR_lstat64 196
#define TARGET_NR_fstat64 197
#define TARGET_NR_lchown32 198
#define TARGET_NR_getuid32 199
#define TARGET_NR_getgid32 200
#define TARGET_NR_geteuid32 201
#define TARGET_NR_getegid32 202
#define TARGET_NR_setreuid32 203
#define TARGET_NR_setregid32 204
#define TARGET_NR_getgroups32 205
#define TARGET_NR_setgroups32 206
#define TARGET_NR_fchown32 207
#define TARGET_NR_setresuid32 208
#define TARGET_NR_getresuid32 209
#define TARGET_NR_setresgid32 210
#define TARGET_NR_getresgid32 211
#define TARGET_NR_chown32 212
#define TARGET_NR_setuid32 213
#define TARGET_NR_setgid32 214
#define TARGET_NR_setfsuid32 215
#define TARGET_NR_setfsgid32 216
#define TARGET_NR_pivot_root 217
#define TARGET_NR_mincore 218
#define TARGET_NR_madvise 219
#define TARGET_NR_madvise1 219 /* delete when C lib stub is removed */
#define TARGET_NR_getdents64 220
#define TARGET_NR_fcntl64 221
/* 223 is unused */
#define TARGET_NR_gettid 224
#define TARGET_NR_readahead 225
#define TARGET_NR_setxattr 226
#define TARGET_NR_lsetxattr 227
#define TARGET_NR_fsetxattr 228
#define TARGET_NR_getxattr 229
#define TARGET_NR_lgetxattr 230
#define TARGET_NR_fgetxattr 231
#define TARGET_NR_listxattr 232
#define TARGET_NR_llistxattr 233
#define TARGET_NR_flistxattr 234
#define TARGET_NR_removexattr 235
#define TARGET_NR_lremovexattr 236
#define TARGET_NR_fremovexattr 237
#define TARGET_NR_tkill 238
#define TARGET_NR_sendfile64 239
#define TARGET_NR_futex 240
#define TARGET_NR_sched_setaffinity 241
#define TARGET_NR_sched_getaffinity 242
#define TARGET_NR_set_thread_area 243
#define TARGET_NR_get_thread_area 244
#define TARGET_NR_io_setup 245
#define TARGET_NR_io_destroy 246
#define TARGET_NR_io_getevents 247
#define TARGET_NR_io_submit 248
#define TARGET_NR_io_cancel 249
#define TARGET_NR_fadvise64 250
#define TARGET_NR_exit_group 252
#define TARGET_NR_lookup_dcookie 253
#define TARGET_NR_epoll_create 254
#define TARGET_NR_epoll_ctl 255
#define TARGET_NR_epoll_wait 256
#define TARGET_NR_remap_file_pages 257
#define TARGET_NR_set_tid_address 258
#define TARGET_NR_timer_create 259
#define TARGET_NR_timer_settime (TARGET_NR_timer_create+1)
#define TARGET_NR_timer_gettime (TARGET_NR_timer_create+2)
#define TARGET_NR_timer_getoverrun (TARGET_NR_timer_create+3)
#define TARGET_NR_timer_delete (TARGET_NR_timer_create+4)
#define TARGET_NR_clock_settime (TARGET_NR_timer_create+5)
#define TARGET_NR_clock_gettime (TARGET_NR_timer_create+6)
#define TARGET_NR_clock_getres (TARGET_NR_timer_create+7)
#define TARGET_NR_clock_nanosleep (TARGET_NR_timer_create+8)

214
linux-user/i386/termbits.h Normal file
View File

@@ -0,0 +1,214 @@
/* from asm/termbits.h */
#define TARGET_NCCS 19
struct target_termios {
unsigned int c_iflag; /* input mode flags */
unsigned int c_oflag; /* output mode flags */
unsigned int c_cflag; /* control mode flags */
unsigned int c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[TARGET_NCCS]; /* control characters */
};
/* c_iflag bits */
#define TARGET_IGNBRK 0000001
#define TARGET_BRKINT 0000002
#define TARGET_IGNPAR 0000004
#define TARGET_PARMRK 0000010
#define TARGET_INPCK 0000020
#define TARGET_ISTRIP 0000040
#define TARGET_INLCR 0000100
#define TARGET_IGNCR 0000200
#define TARGET_ICRNL 0000400
#define TARGET_IUCLC 0001000
#define TARGET_IXON 0002000
#define TARGET_IXANY 0004000
#define TARGET_IXOFF 0010000
#define TARGET_IMAXBEL 0020000
/* c_oflag bits */
#define TARGET_OPOST 0000001
#define TARGET_OLCUC 0000002
#define TARGET_ONLCR 0000004
#define TARGET_OCRNL 0000010
#define TARGET_ONOCR 0000020
#define TARGET_ONLRET 0000040
#define TARGET_OFILL 0000100
#define TARGET_OFDEL 0000200
#define TARGET_NLDLY 0000400
#define TARGET_NL0 0000000
#define TARGET_NL1 0000400
#define TARGET_CRDLY 0003000
#define TARGET_CR0 0000000
#define TARGET_CR1 0001000
#define TARGET_CR2 0002000
#define TARGET_CR3 0003000
#define TARGET_TABDLY 0014000
#define TARGET_TAB0 0000000
#define TARGET_TAB1 0004000
#define TARGET_TAB2 0010000
#define TARGET_TAB3 0014000
#define TARGET_XTABS 0014000
#define TARGET_BSDLY 0020000
#define TARGET_BS0 0000000
#define TARGET_BS1 0020000
#define TARGET_VTDLY 0040000
#define TARGET_VT0 0000000
#define TARGET_VT1 0040000
#define TARGET_FFDLY 0100000
#define TARGET_FF0 0000000
#define TARGET_FF1 0100000
/* c_cflag bit meaning */
#define TARGET_CBAUD 0010017
#define TARGET_B0 0000000 /* hang up */
#define TARGET_B50 0000001
#define TARGET_B75 0000002
#define TARGET_B110 0000003
#define TARGET_B134 0000004
#define TARGET_B150 0000005
#define TARGET_B200 0000006
#define TARGET_B300 0000007
#define TARGET_B600 0000010
#define TARGET_B1200 0000011
#define TARGET_B1800 0000012
#define TARGET_B2400 0000013
#define TARGET_B4800 0000014
#define TARGET_B9600 0000015
#define TARGET_B19200 0000016
#define TARGET_B38400 0000017
#define TARGET_EXTA B19200
#define TARGET_EXTB B38400
#define TARGET_CSIZE 0000060
#define TARGET_CS5 0000000
#define TARGET_CS6 0000020
#define TARGET_CS7 0000040
#define TARGET_CS8 0000060
#define TARGET_CSTOPB 0000100
#define TARGET_CREAD 0000200
#define TARGET_PARENB 0000400
#define TARGET_PARODD 0001000
#define TARGET_HUPCL 0002000
#define TARGET_CLOCAL 0004000
#define TARGET_CBAUDEX 0010000
#define TARGET_B57600 0010001
#define TARGET_B115200 0010002
#define TARGET_B230400 0010003
#define TARGET_B460800 0010004
#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */
#define TARGET_CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
#define TARGET_ISIG 0000001
#define TARGET_ICANON 0000002
#define TARGET_XCASE 0000004
#define TARGET_ECHO 0000010
#define TARGET_ECHOE 0000020
#define TARGET_ECHOK 0000040
#define TARGET_ECHONL 0000100
#define TARGET_NOFLSH 0000200
#define TARGET_TOSTOP 0000400
#define TARGET_ECHOCTL 0001000
#define TARGET_ECHOPRT 0002000
#define TARGET_ECHOKE 0004000
#define TARGET_FLUSHO 0010000
#define TARGET_PENDIN 0040000
#define TARGET_IEXTEN 0100000
/* c_cc character offsets */
#define TARGET_VINTR 0
#define TARGET_VQUIT 1
#define TARGET_VERASE 2
#define TARGET_VKILL 3
#define TARGET_VEOF 4
#define TARGET_VTIME 5
#define TARGET_VMIN 6
#define TARGET_VSWTC 7
#define TARGET_VSTART 8
#define TARGET_VSTOP 9
#define TARGET_VSUSP 10
#define TARGET_VEOL 11
#define TARGET_VREPRINT 12
#define TARGET_VDISCARD 13
#define TARGET_VWERASE 14
#define TARGET_VLNEXT 15
#define TARGET_VEOL2 16
/* ioctls */
#define TARGET_TCGETS 0x5401
#define TARGET_TCSETS 0x5402
#define TARGET_TCSETSW 0x5403
#define TARGET_TCSETSF 0x5404
#define TARGET_TCGETA 0x5405
#define TARGET_TCSETA 0x5406
#define TARGET_TCSETAW 0x5407
#define TARGET_TCSETAF 0x5408
#define TARGET_TCSBRK 0x5409
#define TARGET_TCXONC 0x540A
#define TARGET_TCFLSH 0x540B
#define TARGET_TIOCEXCL 0x540C
#define TARGET_TIOCNXCL 0x540D
#define TARGET_TIOCSCTTY 0x540E
#define TARGET_TIOCGPGRP 0x540F
#define TARGET_TIOCSPGRP 0x5410
#define TARGET_TIOCOUTQ 0x5411
#define TARGET_TIOCSTI 0x5412
#define TARGET_TIOCGWINSZ 0x5413
#define TARGET_TIOCSWINSZ 0x5414
#define TARGET_TIOCMGET 0x5415
#define TARGET_TIOCMBIS 0x5416
#define TARGET_TIOCMBIC 0x5417
#define TARGET_TIOCMSET 0x5418
#define TARGET_TIOCGSOFTCAR 0x5419
#define TARGET_TIOCSSOFTCAR 0x541A
#define TARGET_FIONREAD 0x541B
#define TARGET_TIOCINQ TARGET_FIONREAD
#define TARGET_TIOCLINUX 0x541C
#define TARGET_TIOCCONS 0x541D
#define TARGET_TIOCGSERIAL 0x541E
#define TARGET_TIOCSSERIAL 0x541F
#define TARGET_TIOCPKT 0x5420
#define TARGET_FIONBIO 0x5421
#define TARGET_TIOCNOTTY 0x5422
#define TARGET_TIOCSETD 0x5423
#define TARGET_TIOCGETD 0x5424
#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */
#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */
#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */
#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */
#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */
#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define TARGET_FIOCLEX 0x5451
#define TARGET_FIOASYNC 0x5452
#define TARGET_TIOCSERCONFIG 0x5453
#define TARGET_TIOCSERGWILD 0x5454
#define TARGET_TIOCSERSWILD 0x5455
#define TARGET_TIOCGLCKTRMIOS 0x5456
#define TARGET_TIOCSLCKTRMIOS 0x5457
#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
/* Used for packet mode */
#define TARGET_TIOCPKT_DATA 0
#define TARGET_TIOCPKT_FLUSHREAD 1
#define TARGET_TIOCPKT_FLUSHWRITE 2
#define TARGET_TIOCPKT_STOP 4
#define TARGET_TIOCPKT_START 8
#define TARGET_TIOCPKT_NOSTOP 16
#define TARGET_TIOCPKT_DOSTOP 32
#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */

View File

@@ -1,5 +1,5 @@
/*
* qemu main
* qemu user main
*
* Copyright (c) 2003 Fabrice Bellard
*
@@ -28,19 +28,24 @@
#define DEBUG_LOGFILE "/tmp/qemu.log"
FILE *logfile = NULL;
int loglevel;
#ifdef __APPLE__
#include <crt_externs.h>
# define environ (*_NSGetEnviron())
#endif
static const char *interp_prefix = CONFIG_QEMU_PREFIX;
#ifdef __i386__
#if defined(__i386__) && !defined(CONFIG_STATIC)
/* Force usage of an ELF interpreter even if it is an ELF shared
object ! */
const char interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
#endif
/* for recent libc, we add these dummies symbol which are not declared
/* for recent libc, we add these dummy symbols which are not declared
when generating a linked object (bug in ld ?) */
#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
#if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined(CONFIG_STATIC)
long __preinit_array_start[0];
long __preinit_array_end[0];
long __init_array_start[0];
long __init_array_end[0];
long __fini_array_start[0];
@@ -61,48 +66,88 @@ void gemu_log(const char *fmt, ...)
va_end(ap);
}
#ifdef TARGET_I386
/***********************************************************/
/* CPUX86 core interface */
void cpu_x86_outb(CPUX86State *env, int addr, int val)
void cpu_outb(CPUState *env, int addr, int val)
{
fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
}
void cpu_x86_outw(CPUX86State *env, int addr, int val)
void cpu_outw(CPUState *env, int addr, int val)
{
fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
}
void cpu_x86_outl(CPUX86State *env, int addr, int val)
void cpu_outl(CPUState *env, int addr, int val)
{
fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
}
int cpu_x86_inb(CPUX86State *env, int addr)
int cpu_inb(CPUState *env, int addr)
{
fprintf(stderr, "inb: port=0x%04x\n", addr);
return 0;
}
int cpu_x86_inw(CPUX86State *env, int addr)
int cpu_inw(CPUState *env, int addr)
{
fprintf(stderr, "inw: port=0x%04x\n", addr);
return 0;
}
int cpu_x86_inl(CPUX86State *env, int addr)
int cpu_inl(CPUState *env, int addr)
{
fprintf(stderr, "inl: port=0x%04x\n", addr);
return 0;
}
int cpu_x86_get_pic_interrupt(CPUX86State *env)
int cpu_get_pic_interrupt(CPUState *env)
{
return -1;
}
/* timers for rdtsc */
#if defined(__i386__)
int64_t cpu_get_real_ticks(void)
{
int64_t val;
asm volatile ("rdtsc" : "=A" (val));
return val;
}
#elif defined(__x86_64__)
int64_t cpu_get_real_ticks(void)
{
uint32_t low,high;
int64_t val;
asm volatile("rdtsc" : "=a" (low), "=d" (high));
val = high;
val <<= 32;
val |= low;
return val;
}
#else
static uint64_t emu_time;
int64_t cpu_get_real_ticks(void)
{
return emu_time++;
}
#endif
#ifdef TARGET_I386
/***********************************************************/
/* CPUX86 core interface */
uint64_t cpu_get_tsc(CPUX86State *env)
{
return cpu_get_real_ticks();
}
static void write_dt(void *ptr, unsigned long addr, unsigned long limit,
int flags)
{
@@ -246,6 +291,27 @@ void cpu_loop(CPUX86State *env)
#ifdef TARGET_ARM
/* XXX: find a better solution */
extern void tb_invalidate_page_range(target_ulong start, target_ulong end);
static void arm_cache_flush(target_ulong start, target_ulong last)
{
target_ulong addr, last1;
if (last < start)
return;
addr = start;
for(;;) {
last1 = ((addr + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK) - 1;
if (last1 > last)
last1 = last;
tb_invalidate_page_range(addr, last1 + 1);
if (last1 == last)
break;
addr = last1 + 1;
}
}
void cpu_loop(CPUARMState *env)
{
int trapnr;
@@ -256,18 +322,34 @@ void cpu_loop(CPUARMState *env)
trapnr = cpu_arm_exec(env);
switch(trapnr) {
case EXCP_UDEF:
info.si_signo = SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPN;
info._sifields._sigfault._addr = env->regs[15];
queue_signal(info.si_signo, &info);
{
TaskState *ts = env->opaque;
uint32_t opcode;
/* we handle the FPU emulation here, as Linux */
/* we get the opcode */
opcode = ldl_raw((uint8_t *)env->regs[15]);
if (EmulateAll(opcode, &ts->fpa, env->regs) == 0) {
info.si_signo = SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLOPN;
info._sifields._sigfault._addr = env->regs[15];
queue_signal(info.si_signo, &info);
} else {
/* increment PC */
env->regs[15] += 4;
}
}
break;
case EXCP_SWI:
{
/* system call */
insn = ldl((void *)(env->regs[15] - 4));
n = insn & 0xffffff;
if (n >= ARM_SYSCALL_BASE) {
if (n == ARM_NR_cacheflush) {
arm_cache_flush(env->regs[0], env->regs[1]);
} else if (n >= ARM_SYSCALL_BASE) {
/* linux syscall */
n -= ARM_SYSCALL_BASE;
env->regs[0] = do_syscall(env,
@@ -299,10 +381,524 @@ void cpu_loop(CPUARMState *env)
#endif
#ifdef TARGET_SPARC
//#define DEBUG_WIN
/* WARNING: dealing with register windows _is_ complicated */
static inline int get_reg_index(CPUSPARCState *env, int cwp, int index)
{
index = (index + cwp * 16) & (16 * NWINDOWS - 1);
/* wrap handling : if cwp is on the last window, then we use the
registers 'after' the end */
if (index < 8 && env->cwp == (NWINDOWS - 1))
index += (16 * NWINDOWS);
return index;
}
static inline void save_window_offset(CPUSPARCState *env, int offset)
{
unsigned int new_wim, i, cwp1;
uint32_t *sp_ptr;
new_wim = ((env->wim >> 1) | (env->wim << (NWINDOWS - 1))) &
((1LL << NWINDOWS) - 1);
/* save the window */
cwp1 = (env->cwp + offset) & (NWINDOWS - 1);
sp_ptr = (uint32_t *)(env->regbase[get_reg_index(env, cwp1, 6)]);
#if defined(DEBUG_WIN)
printf("win_overflow: sp_ptr=0x%x save_cwp=%d\n",
(int)sp_ptr, cwp1);
#endif
for(i = 0; i < 16; i++)
stl_raw(sp_ptr + i, env->regbase[get_reg_index(env, cwp1, 8 + i)]);
env->wim = new_wim;
}
static void save_window(CPUSPARCState *env)
{
save_window_offset(env, 2);
}
static void restore_window(CPUSPARCState *env)
{
unsigned int new_wim, i, cwp1;
uint32_t *sp_ptr;
new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) &
((1LL << NWINDOWS) - 1);
/* restore the invalid window */
cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
sp_ptr = (uint32_t *)(env->regbase[get_reg_index(env, cwp1, 6)]);
#if defined(DEBUG_WIN)
printf("win_underflow: sp_ptr=0x%x load_cwp=%d\n",
(int)sp_ptr, cwp1);
#endif
for(i = 0; i < 16; i++)
env->regbase[get_reg_index(env, cwp1, 8 + i)] = ldl_raw(sp_ptr + i);
env->wim = new_wim;
}
static void flush_windows(CPUSPARCState *env)
{
int offset, cwp1;
#if defined(DEBUG_WIN)
printf("flush_windows:\n");
#endif
offset = 2;
for(;;) {
/* if restore would invoke restore_window(), then we can stop */
cwp1 = (env->cwp + 1) & (NWINDOWS - 1);
if (env->wim & (1 << cwp1))
break;
#if defined(DEBUG_WIN)
printf("offset=%d: ", offset);
#endif
save_window_offset(env, offset);
offset++;
}
}
void cpu_loop (CPUSPARCState *env)
{
int trapnr, ret;
while (1) {
trapnr = cpu_sparc_exec (env);
switch (trapnr) {
case 0x88:
case 0x90:
ret = do_syscall (env, env->gregs[1],
env->regwptr[0], env->regwptr[1],
env->regwptr[2], env->regwptr[3],
env->regwptr[4], env->regwptr[5]);
if ((unsigned int)ret >= (unsigned int)(-515)) {
env->psr |= PSR_CARRY;
ret = -ret;
} else {
env->psr &= ~PSR_CARRY;
}
env->regwptr[0] = ret;
/* next instruction */
env->pc = env->npc;
env->npc = env->npc + 4;
break;
case 0x83: /* flush windows */
// flush_windows(env);
/* next instruction */
env->pc = env->npc;
env->npc = env->npc + 4;
break;
case TT_WIN_OVF: /* window overflow */
save_window(env);
break;
case TT_WIN_UNF: /* window underflow */
restore_window(env);
break;
default:
printf ("Unhandled trap: 0x%x\n", trapnr);
cpu_sparc_dump_state(env, stderr, 0);
exit (1);
}
process_pending_signals (env);
}
}
#endif
#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)
{
target_siginfo_t info;
int trapnr;
uint32_t ret;
for(;;) {
trapnr = cpu_ppc_exec(env);
if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
trapnr != EXCP_TRACE) {
if (loglevel > 0) {
cpu_ppc_dump_state(env, logfile, 0);
}
}
switch(trapnr) {
case EXCP_NONE:
break;
case EXCP_SYSCALL_USER:
/* system call */
/* WARNING:
* PPC ABI uses overflow flag in cr0 to signal an error
* in syscalls.
*/
#if 0
printf("syscall %d 0x%08x 0x%08x 0x%08x 0x%08x\n", env->gpr[0],
env->gpr[3], env->gpr[4], env->gpr[5], env->gpr[6]);
#endif
env->crf[0] &= ~0x1;
ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
env->gpr[5], env->gpr[6], env->gpr[7],
env->gpr[8]);
if (ret > (uint32_t)(-515)) {
env->crf[0] |= 0x1;
ret = -ret;
}
env->gpr[3] = ret;
#if 0
printf("syscall returned 0x%08x (%d)\n", ret, ret);
#endif
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 = TARGET_SIGBUS;
info.si_errno = 0;
info.si_code = TARGET_BUS_OBJERR;
info._sifields._sigfault._addr = env->nip - 4;
queue_signal(info.si_signo, &info);
case EXCP_DSI:
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]);
}
switch (env->error_code & 0xF) {
case EXCP_DSI_TRANSLATE:
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
break;
case EXCP_DSI_NOTSUP:
case EXCP_DSI_EXTERNAL:
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLADR;
break;
case EXCP_DSI_PROT:
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_ACCERR;
break;
case EXCP_DSI_DABR:
info.si_signo = TARGET_SIGTRAP;
info.si_errno = 0;
info.si_code = TARGET_TRAP_BRKPT;
break;
default:
/* Let's send a regular segfault... */
fprintf(stderr, "Invalid segfault errno (%02x)\n",
env->error_code);
if (loglevel) {
fprintf(logfile, "Invalid segfault errno (%02x)\n",
env->error_code);
}
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
break;
}
info._sifields._sigfault._addr = 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");
switch (env->error_code) {
case EXCP_ISI_TRANSLATE:
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
break;
case EXCP_ISI_GUARD:
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLADR;
break;
case EXCP_ISI_NOEXEC:
case EXCP_ISI_PROT:
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_ACCERR;
break;
default:
/* Let's send a regular segfault... */
fprintf(stderr, "Invalid segfault errno (%02x)\n",
env->error_code);
if (loglevel) {
fprintf(logfile, "Invalid segfault errno (%02x)\n",
env->error_code);
}
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
break;
}
info._sifields._sigfault._addr = 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 = TARGET_SIGBUS;
info.si_errno = 0;
info.si_code = TARGET_BUS_ADRALN;
info._sifields._sigfault._addr = 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 = TARGET_SIGFPE;
info.si_errno = 0;
switch (env->error_code & 0xF) {
case EXCP_FP_OX:
info.si_code = TARGET_FPE_FLTOVF;
break;
case EXCP_FP_UX:
info.si_code = TARGET_FPE_FLTUND;
break;
case EXCP_FP_ZX:
case EXCP_FP_VXZDZ:
info.si_code = TARGET_FPE_FLTDIV;
break;
case EXCP_FP_XX:
info.si_code = TARGET_FPE_FLTRES;
break;
case EXCP_FP_VXSOFT:
info.si_code = TARGET_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 = TARGET_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 = TARGET_SIGILL;
info.si_errno = 0;
switch (env->error_code & 0xF) {
case EXCP_INVAL_INVAL:
info.si_code = TARGET_ILL_ILLOPC;
break;
case EXCP_INVAL_LSWX:
info.si_code = TARGET_ILL_ILLOPN;
break;
case EXCP_INVAL_SPR:
info.si_code = TARGET_ILL_PRVREG;
break;
case EXCP_INVAL_FP:
info.si_code = TARGET_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 = TARGET_ILL_ILLADR;
break;
}
break;
case EXCP_PRIV:
fprintf(stderr, "Privilege violation\n");
if (loglevel)
fprintf(logfile, "Privilege violation\n");
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
switch (env->error_code & 0xF) {
case EXCP_PRIV_OPC:
info.si_code = TARGET_ILL_PRVOPC;
break;
case EXCP_PRIV_REG:
info.si_code = TARGET_ILL_PRVREG;
break;
default:
fprintf(stderr, "Unknown privilege violation (%02x)\n",
env->error_code & 0xF);
info.si_code = TARGET_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._sifields._sigfault._addr = 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 = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_COPROC;
info._sifields._sigfault._addr = 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_RESA: /* Implementation specific */
/* Should not happen ! */
fprintf(stderr, "RESA exception should never happen !\n");
if (loglevel)
fprintf(logfile, "RESA exception should never happen !\n");
abort();
case EXCP_RESB: /* Implementation specific */
/* Should not happen ! */
fprintf(stderr, "RESB exception should never happen !\n");
if (loglevel)
fprintf(logfile, "RESB exception should never happen !\n");
abort();
case EXCP_TRACE:
/* Do nothing: we use this to trace execution */
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_RFI:
/* Should not occur: we always are in user mode */
fprintf(stderr, "Return from interrupt ?\n");
if (loglevel)
fprintf(logfile, "Return from interrupt ?\n");
abort();
case EXCP_INTERRUPT:
/* Don't know why this should ever happen... */
break;
case EXCP_DEBUG:
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
void usage(void)
{
printf("qemu version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
"usage: qemu [-h] [-d] [-L path] [-s size] program [arguments...]\n"
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"
"Linux CPU emulator (compiled for %s emulation)\n"
"\n"
"-h print this help\n"
@@ -310,7 +906,10 @@ void usage(void)
"-s size set the stack size in bytes (default=%ld)\n"
"\n"
"debug options:\n"
"-d activate log (logfile=%s)\n"
#ifdef USE_CODE_COPY
"-no-code-copy disable code copy acceleration\n"
#endif
"-d options activate log (logfile=%s)\n"
"-p pagesize set the host page size to 'pagesize'\n",
TARGET_ARCH,
interp_prefix,
@@ -340,7 +939,9 @@ int main(int argc, char **argv)
if (argc <= 1)
usage();
loglevel = 0;
/* init debug */
cpu_set_log_filename(DEBUG_LOGFILE);
optind = 1;
for(;;) {
if (optind >= argc)
@@ -353,7 +954,22 @@ int main(int argc, char **argv)
if (!strcmp(r, "-")) {
break;
} else if (!strcmp(r, "d")) {
loglevel = 1;
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++];
x86_stack_size = strtol(r, (char **)&r, 0);
@@ -366,13 +982,19 @@ int main(int argc, char **argv)
} else if (!strcmp(r, "L")) {
interp_prefix = argv[optind++];
} else if (!strcmp(r, "p")) {
host_page_size = atoi(argv[optind++]);
if (host_page_size == 0 ||
(host_page_size & (host_page_size - 1)) != 0) {
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 {
} else
#ifdef USE_CODE_COPY
if (!strcmp(r, "no-code-copy")) {
code_copy_enabled = 0;
} else
#endif
{
usage();
}
}
@@ -380,16 +1002,6 @@ int main(int argc, char **argv)
usage();
filename = argv[optind];
/* init debug */
if (loglevel) {
logfile = fopen(DEBUG_LOGFILE, "w");
if (!logfile) {
perror(DEBUG_LOGFILE);
_exit(1);
}
setvbuf(logfile, NULL, _IOLBF, 0);
}
/* Zero out regs */
memset(regs, 0, sizeof(struct target_pt_regs));
@@ -399,8 +1011,8 @@ int main(int argc, char **argv)
/* Scan interp_prefix dir for replacement files. */
init_paths(interp_prefix);
/* NOTE: we need to init the CPU at this stage to get the
host_page_size */
/* NOTE: we need to init the CPU at this stage to get
qemu_host_page_size */
env = cpu_init();
if (elf_exec(filename, argv+optind, environ, regs, info) != 0) {
@@ -433,6 +1045,14 @@ int main(int argc, char **argv)
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;
/* flags setup : we activate the IRQs by default as in user mode */
env->eflags |= IF_MASK;
/* linux register setup */
env->regs[R_EAX] = regs->eax;
env->regs[R_EBX] = regs->ebx;
@@ -493,6 +1113,29 @@ int main(int argc, char **argv)
}
env->cpsr = regs->uregs[16];
}
#elif defined(TARGET_SPARC)
{
int i;
env->pc = regs->pc;
env->npc = regs->npc;
env->y = regs->y;
for(i = 0; i < 8; i++)
env->gregs[i] = regs->u_regs[i];
for(i = 0; i < 8; i++)
env->regwptr[i] = regs->u_regs[i + 8];
}
#elif defined(TARGET_PPC)
{
int i;
for (i = 0; i < 32; i++) {
if (i != 12 && i != 6)
env->msr[i] = (regs->msr >> i) & 1;
}
env->nip = regs->nip;
for(i = 0; i < 32; i++) {
env->gpr[i] = regs->gpr[i];
}
}
#else
#error unsupported target CPU
#endif

View File

@@ -53,7 +53,7 @@ int target_mprotect(unsigned long start, unsigned long len, int prot)
if (len == 0)
return 0;
host_start = start & host_page_mask;
host_start = start & qemu_host_page_mask;
host_end = HOST_PAGE_ALIGN(end);
if (start > host_start) {
/* handle host page containing start */
@@ -61,27 +61,27 @@ int target_mprotect(unsigned long start, unsigned long len, int prot)
for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
prot1 |= page_get_flags(addr);
}
if (host_end == host_start + host_page_size) {
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, host_page_size, prot1 & PAGE_BITS);
ret = mprotect((void *)host_start, qemu_host_page_size, prot1 & PAGE_BITS);
if (ret != 0)
return ret;
host_start += host_page_size;
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 - host_page_size), host_page_size,
ret = mprotect((void *)(host_end - qemu_host_page_size), qemu_host_page_size,
prot1 & PAGE_BITS);
if (ret != 0)
return ret;
host_end -= host_page_size;
host_end -= qemu_host_page_size;
}
/* handle the pages in the middle */
@@ -102,7 +102,7 @@ int mmap_frag(unsigned long host_start,
unsigned long host_end, ret, addr;
int prot1, prot_new;
host_end = host_start + host_page_size;
host_end = host_start + qemu_host_page_size;
/* get the protection of the target pages outside the mapping */
prot1 = 0;
@@ -113,7 +113,7 @@ int mmap_frag(unsigned long host_start,
if (prot1 == 0) {
/* no page was there, so we allocate one */
ret = (long)mmap((void *)host_start, host_page_size, prot,
ret = (long)mmap((void *)host_start, qemu_host_page_size, prot,
flags | MAP_ANONYMOUS, -1, 0);
if (ret == -1)
return ret;
@@ -130,18 +130,18 @@ int mmap_frag(unsigned long host_start,
/* adjust protection to be able to read */
if (!(prot1 & PROT_WRITE))
mprotect((void *)host_start, host_page_size, 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, host_page_size, prot_new);
mprotect((void *)host_start, qemu_host_page_size, prot_new);
} else {
/* just update the protection */
if (prot_new != prot1) {
mprotect((void *)host_start, host_page_size, prot_new);
mprotect((void *)host_start, qemu_host_page_size, prot_new);
}
}
return 0;
@@ -152,6 +152,9 @@ 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
{
@@ -185,18 +188,20 @@ long target_mmap(unsigned long start, unsigned long len, int prot,
len = TARGET_PAGE_ALIGN(len);
if (len == 0)
return start;
host_start = start & host_page_mask;
host_start = start & qemu_host_page_mask;
if (!(flags & MAP_FIXED)) {
#if defined(__alpha__) || defined(__sparc__)
#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 = 0x40000000;
if (host_start == 0) {
host_start = last_start;
last_start += HOST_PAGE_ALIGN(len);
}
#endif
if (host_page_size != real_host_page_size) {
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) + host_page_size - TARGET_PAGE_SIZE;
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)
@@ -212,7 +217,7 @@ long target_mmap(unsigned long start, unsigned long len, int prot,
flags |= MAP_FIXED;
} else {
/* if not fixed, no need to do anything */
host_offset = offset & host_page_mask;
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);
@@ -233,7 +238,7 @@ long target_mmap(unsigned long start, unsigned long len, int prot,
/* worst case: we cannot map the file because the offset is not
aligned, so we read it */
if (!(flags & MAP_ANONYMOUS) &&
(offset & ~host_page_mask) != (start & ~host_page_mask)) {
(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 */
if ((flags & MAP_TYPE) == MAP_SHARED &&
@@ -255,7 +260,7 @@ long target_mmap(unsigned long start, unsigned long len, int prot,
/* handle the start of the mapping */
if (start > host_start) {
if (host_end == host_start + host_page_size) {
if (host_end == host_start + qemu_host_page_size) {
/* one single host page */
ret = mmap_frag(host_start, start, end,
prot, flags, fd, offset);
@@ -263,21 +268,21 @@ long target_mmap(unsigned long start, unsigned long len, int prot,
return ret;
goto the_end1;
}
ret = mmap_frag(host_start, start, host_start + host_page_size,
ret = mmap_frag(host_start, start, host_start + qemu_host_page_size,
prot, flags, fd, offset);
if (ret == -1)
return ret;
host_start += host_page_size;
host_start += qemu_host_page_size;
}
/* handle the end of the mapping */
if (end < host_end) {
ret = mmap_frag(host_end - host_page_size,
host_end - host_page_size, 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 - host_page_size - start);
offset + host_end - qemu_host_page_size - start);
if (ret == -1)
return ret;
host_end -= host_page_size;
host_end -= qemu_host_page_size;
}
/* map the middle (easier) */
@@ -317,7 +322,7 @@ int target_munmap(unsigned long start, unsigned long len)
if (len == 0)
return -EINVAL;
end = start + len;
host_start = start & host_page_mask;
host_start = start & qemu_host_page_mask;
host_end = HOST_PAGE_ALIGN(end);
if (start > host_start) {
@@ -326,14 +331,14 @@ int target_munmap(unsigned long start, unsigned long len)
for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
prot |= page_get_flags(addr);
}
if (host_end == host_start + host_page_size) {
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 += host_page_size;
host_start += qemu_host_page_size;
}
if (end < host_end) {
prot = 0;
@@ -341,7 +346,7 @@ int target_munmap(unsigned long start, unsigned long len)
prot |= page_get_flags(addr);
}
if (prot != 0)
host_end -= host_page_size;
host_end -= qemu_host_page_size;
}
/* unmap what we can */
@@ -386,7 +391,7 @@ int target_msync(unsigned long start, unsigned long len, int flags)
if (end == start)
return 0;
start &= host_page_mask;
start &= qemu_host_page_mask;
return msync((void *)start, end - start, flags);
}

129
linux-user/ppc/syscall.h Normal file
View File

@@ -0,0 +1,129 @@
/*
* PPC emulation for qemu: syscall definitions.
*
* Copyright (c) 2003 Jocelyn Mayer
*
* 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
*/
/* XXX: ABSOLUTELY BUGGY:
* for now, this is quite just a cut-and-paste from i386 target...
*/
/* default linux values for the selectors */
#define __USER_DS (1)
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 */
};
/* ioctls */
struct target_revectored_struct {
target_ulong __map[8]; /* 256 bits */
};
/*
* flags masks
*/
/* ipcs */
#define TARGET_SEMOP 1
#define TARGET_SEMGET 2
#define TARGET_SEMCTL 3
#define TARGET_MSGSND 11
#define TARGET_MSGRCV 12
#define TARGET_MSGGET 13
#define TARGET_MSGCTL 14
#define TARGET_SHMAT 21
#define TARGET_SHMDT 22
#define TARGET_SHMGET 23
#define TARGET_SHMCTL 24
struct target_msgbuf {
int mtype;
char mtext[1];
};
struct target_ipc_kludge {
unsigned int msgp; /* Really (struct msgbuf *) */
int msgtyp;
};
struct target_ipc_perm {
int key;
unsigned short uid;
unsigned short gid;
unsigned short cuid;
unsigned short cgid;
unsigned short mode;
unsigned short seq;
};
struct target_msqid_ds {
struct target_ipc_perm msg_perm;
unsigned int msg_first; /* really struct target_msg* */
unsigned int msg_last; /* really struct target_msg* */
unsigned int msg_stime; /* really target_time_t */
unsigned int msg_rtime; /* really target_time_t */
unsigned int msg_ctime; /* really target_time_t */
unsigned int wwait; /* really struct wait_queue* */
unsigned int rwait; /* really struct wait_queue* */
unsigned short msg_cbytes;
unsigned short msg_qnum;
unsigned short msg_qbytes;
unsigned short msg_lspid;
unsigned short msg_lrpid;
};
struct target_shmid_ds {
struct target_ipc_perm shm_perm;
int shm_segsz;
unsigned int shm_atime; /* really target_time_t */
unsigned int shm_dtime; /* really target_time_t */
unsigned int shm_ctime; /* really target_time_t */
unsigned short shm_cpid;
unsigned short shm_lpid;
short shm_nattch;
unsigned short shm_npages;
unsigned long *shm_pages;
void *attaches; /* really struct shm_desc * */
};
#define TARGET_IPC_RMID 0
#define TARGET_IPC_SET 1
#define TARGET_IPC_STAT 2
union target_semun {
int val;
unsigned int buf; /* really struct semid_ds * */
unsigned int array; /* really unsigned short * */
unsigned int __buf; /* really struct seminfo * */
unsigned int __pad; /* really void* */
};

258
linux-user/ppc/syscall_nr.h Normal file
View File

@@ -0,0 +1,258 @@
/*
* This file contains the system call numbers.
*/
#define TARGET_NR_restart_syscall 0
#define TARGET_NR_exit 1
#define TARGET_NR_fork 2
#define TARGET_NR_read 3
#define TARGET_NR_write 4
#define TARGET_NR_open 5
#define TARGET_NR_close 6
#define TARGET_NR_waitpid 7
#define TARGET_NR_creat 8
#define TARGET_NR_link 9
#define TARGET_NR_unlink 10
#define TARGET_NR_execve 11
#define TARGET_NR_chdir 12
#define TARGET_NR_time 13
#define TARGET_NR_mknod 14
#define TARGET_NR_chmod 15
#define TARGET_NR_lchown32 16
#define TARGET_NR_break 17
#define TARGET_NR_oldstat 18
#define TARGET_NR_lseek 19
#define TARGET_NR_getpid 20
#define TARGET_NR_mount 21
#define TARGET_NR_umount 22
#define TARGET_NR_setuid32 23
#define TARGET_NR_getuid32 24
#define TARGET_NR_stime 25
#define TARGET_NR_ptrace 26
#define TARGET_NR_alarm 27
#define TARGET_NR_oldfstat 28
#define TARGET_NR_pause 29
#define TARGET_NR_utime 30
#define TARGET_NR_stty 31
#define TARGET_NR_gtty 32
#define TARGET_NR_access 33
#define TARGET_NR_nice 34
#define TARGET_NR_ftime 35
#define TARGET_NR_sync 36
#define TARGET_NR_kill 37
#define TARGET_NR_rename 38
#define TARGET_NR_mkdir 39
#define TARGET_NR_rmdir 40
#define TARGET_NR_dup 41
#define TARGET_NR_pipe 42
#define TARGET_NR_times 43
#define TARGET_NR_prof 44
#define TARGET_NR_brk 45
#define TARGET_NR_setgid32 46
#define TARGET_NR_getgid32 47
#define TARGET_NR_signal 48
#define TARGET_NR_geteuid32 49
#define TARGET_NR_getegid32 50
#define TARGET_NR_acct 51
#define TARGET_NR_umount2 52
#define TARGET_NR_lock 53
#define TARGET_NR_ioctl 54
#define TARGET_NR_fcntl 55
#define TARGET_NR_mpx 56
#define TARGET_NR_setpgid 57
#define TARGET_NR_ulimit 58
#define TARGET_NR_oldolduname 59
#define TARGET_NR_umask 60
#define TARGET_NR_chroot 61
#define TARGET_NR_ustat 62
#define TARGET_NR_dup2 63
#define TARGET_NR_getppid 64
#define TARGET_NR_getpgrp 65
#define TARGET_NR_setsid 66
#define TARGET_NR_sigaction 67
#define TARGET_NR_sgetmask 68
#define TARGET_NR_ssetmask 69
#define TARGET_NR_setreuid32 70
#define TARGET_NR_setregid32 71
#define TARGET_NR_sigsuspend 72
#define TARGET_NR_sigpending 73
#define TARGET_NR_sethostname 74
#define TARGET_NR_setrlimit 75
#define TARGET_NR_getrlimit 76
#define TARGET_NR_getrusage 77
#define TARGET_NR_gettimeofday 78
#define TARGET_NR_settimeofday 79
#define TARGET_NR_getgroups32 80
#define TARGET_NR_setgroups32 81
#define TARGET_NR_select 82
#define TARGET_NR_symlink 83
#define TARGET_NR_oldlstat 84
#define TARGET_NR_readlink 85
#define TARGET_NR_uselib 86
#define TARGET_NR_swapon 87
#define TARGET_NR_reboot 88
#define TARGET_NR_readdir 89
#define TARGET_NR_mmap 90
#define TARGET_NR_munmap 91
#define TARGET_NR_truncate 92
#define TARGET_NR_ftruncate 93
#define TARGET_NR_fchmod 94
#define TARGET_NR_fchown32 95
#define TARGET_NR_getpriority 96
#define TARGET_NR_setpriority 97
#define TARGET_NR_profil 98
#define TARGET_NR_statfs 99
#define TARGET_NR_fstatfs 100
#define TARGET_NR_ioperm 101
#define TARGET_NR_socketcall 102
#define TARGET_NR_syslog 103
#define TARGET_NR_setitimer 104
#define TARGET_NR_getitimer 105
#define TARGET_NR_stat 106
#define TARGET_NR_lstat 107
#define TARGET_NR_fstat 108
#define TARGET_NR_olduname 109
#define TARGET_NR_iopl 110
#define TARGET_NR_vhangup 111
#define TARGET_NR_idle 112
#define TARGET_NR_vm86 113
#define TARGET_NR_wait4 114
#define TARGET_NR_swapoff 115
#define TARGET_NR_sysinfo 116
#define TARGET_NR_ipc 117
#define TARGET_NR_fsync 118
#define TARGET_NR_sigreturn 119
#define TARGET_NR_clone 120
#define TARGET_NR_setdomainname 121
#define TARGET_NR_uname 122
#define TARGET_NR_modify_ldt 123
#define TARGET_NR_adjtimex 124
#define TARGET_NR_mprotect 125
#define TARGET_NR_sigprocmask 126
#define TARGET_NR_create_module 127
#define TARGET_NR_init_module 128
#define TARGET_NR_delete_module 129
#define TARGET_NR_get_kernel_syms 130
#define TARGET_NR_quotactl 131
#define TARGET_NR_getpgid 132
#define TARGET_NR_fchdir 133
#define TARGET_NR_bdflush 134
#define TARGET_NR_sysfs 135
#define TARGET_NR_personality 136
#define TARGET_NR_afs_syscall 137 /* Syscall for Andrew File System */
#define TARGET_NR_setfsuid32 138
#define TARGET_NR_setfsgid32 139
#define TARGET_NR__llseek 140
#define TARGET_NR_getdents 141
#define TARGET_NR__newselect 142
#define TARGET_NR_flock 143
#define TARGET_NR_msync 144
#define TARGET_NR_readv 145
#define TARGET_NR_writev 146
#define TARGET_NR_getsid 147
#define TARGET_NR_fdatasync 148
#define TARGET_NR__sysctl 149
#define TARGET_NR_mlock 150
#define TARGET_NR_munlock 151
#define TARGET_NR_mlockall 152
#define TARGET_NR_munlockall 153
#define TARGET_NR_sched_setparam 154
#define TARGET_NR_sched_getparam 155
#define TARGET_NR_sched_setscheduler 156
#define TARGET_NR_sched_getscheduler 157
#define TARGET_NR_sched_yield 158
#define TARGET_NR_sched_get_priority_max 159
#define TARGET_NR_sched_get_priority_min 160
#define TARGET_NR_sched_rr_get_interval 161
#define TARGET_NR_nanosleep 162
#define TARGET_NR_mremap 163
#define TARGET_NR_setresuid32 164
#define TARGET_NR_getresuid32 165
#define TARGET_NR_query_module 166
#define TARGET_NR_poll 167
#define TARGET_NR_nfsservctl 168
#define TARGET_NR_setresgid32 169
#define TARGET_NR_getresgid32 170
#define TARGET_NR_prctl 171
#define TARGET_NR_rt_sigreturn 172
#define TARGET_NR_rt_sigaction 173
#define TARGET_NR_rt_sigprocmask 174
#define TARGET_NR_rt_sigpending 175
#define TARGET_NR_rt_sigtimedwait 176
#define TARGET_NR_rt_sigqueueinfo 177
#define TARGET_NR_rt_sigsuspend 178
#define TARGET_NR_pread64 179
#define TARGET_NR_pwrite64 180
#define TARGET_NR_chown32 181
#define TARGET_NR_getcwd 182
#define TARGET_NR_capget 183
#define TARGET_NR_capset 184
#define TARGET_NR_sigaltstack 185
#define TARGET_NR_sendfile 186
#define TARGET_NR_getpmsg 187 /* some people actually want streams */
#define TARGET_NR_putpmsg 188 /* some people actually want streams */
#define TARGET_NR_vfork 189
#define TARGET_NR_ugetrlimit 190 /* SuS compliant getrlimit */
#define TARGET_NR_readahead 191
#define TARGET_NR_mmap2 192
#define TARGET_NR_truncate64 193
#define TARGET_NR_ftruncate64 194
#define TARGET_NR_stat64 195
#define TARGET_NR_lstat64 196
#define TARGET_NR_fstat64 197
#define TARGET_NR_pciconfig_read 198
#define TARGET_NR_pciconfig_write 199
#define TARGET_NR_pciconfig_iobase 200
#define TARGET_NR_multiplexer 201
#define TARGET_NR_getdents64 202
#define TARGET_NR_pivot_root 203
#define TARGET_NR_fcntl64 204
#define TARGET_NR_madvise 205
#define TARGET_NR_mincore 206
#define TARGET_NR_gettid 207
#define TARGET_NR_tkill 208
#define TARGET_NR_setxattr 209
#define TARGET_NR_lsetxattr 210
#define TARGET_NR_fsetxattr 211
#define TARGET_NR_getxattr 212
#define TARGET_NR_lgetxattr 213
#define TARGET_NR_fgetxattr 214
#define TARGET_NR_listxattr 215
#define TARGET_NR_llistxattr 216
#define TARGET_NR_flistxattr 217
#define TARGET_NR_removexattr 218
#define TARGET_NR_lremovexattr 219
#define TARGET_NR_fremovexattr 220
#define TARGET_NR_futex 221
#define TARGET_NR_sched_setaffinity 222
#define TARGET_NR_sched_getaffinity 223
/* 224 currently unused */
#define TARGET_NR_tuxcall 225
#define TARGET_NR_sendfile64 226
#define TARGET_NR_io_setup 227
#define TARGET_NR_io_destroy 228
#define TARGET_NR_io_getevents 229
#define TARGET_NR_io_submit 230
#define TARGET_NR_io_cancel 231
#define TARGET_NR_set_tid_address 232
#define TARGET_NR_fadvise64 233
#define TARGET_NR_exit_group 234
#define TARGET_NR_lookup_dcookie 235
#define TARGET_NR_epoll_create 236
#define TARGET_NR_epoll_ctl 237
#define TARGET_NR_epoll_wait 238
#define TARGET_NR_remap_file_pages 239
#define TARGET_NR_timer_create 240
#define TARGET_NR_timer_settime 241
#define TARGET_NR_timer_gettime 242
#define TARGET_NR_timer_getoverrun 243
#define TARGET_NR_timer_delete 244
#define TARGET_NR_clock_settime 245
#define TARGET_NR_clock_gettime 246
#define TARGET_NR_clock_getres 247
#define TARGET_NR_clock_nanosleep 248
#define TARGET_NR_swapcontext 249
#define TARGET_NR_tgkill 250
#define TARGET_NR_utimes 251
#define TARGET_NR_statfs64 252
#define TARGET_NR_fstatfs64 253
#define TARGET_NR_fadvise64_64 254

235
linux-user/ppc/termbits.h Normal file
View File

@@ -0,0 +1,235 @@
/* from asm/termbits.h */
#define TARGET_NCCS 19
struct target_termios {
unsigned int c_iflag; /* input mode flags */
unsigned int c_oflag; /* output mode flags */
unsigned int c_cflag; /* control mode flags */
unsigned int c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[TARGET_NCCS]; /* control characters */
unsigned int c_ispeed; /* input speed */
unsigned int c_ospeed; /* output speed */
};
/* c_cc character offsets */
#define TARGET_VINTR 0
#define TARGET_VQUIT 1
#define TARGET_VERASE 2
#define TARGET_VKILL 3
#define TARGET_VEOF 4
#define TARGET_VMIN 5
#define TARGET_VEOL 6
#define TARGET_VTIME 7
#define TARGET_VEOL2 8
#define TARGET_VSWTC 9
#define TARGET_VWERASE 10
#define TARGET_VREPRINT 11
#define TARGET_VSUSP 12
#define TARGET_VSTART 13
#define TARGET_VSTOP 14
#define TARGET_VLNEXT 15
#define TARGET_VDISCARD 16
#define TARGET_IGNBRK 0000001
#define TARGET_BRKINT 0000002
#define TARGET_IGNPAR 0000004
#define TARGET_PARMRK 0000010
#define TARGET_INPCK 0000020
#define TARGET_ISTRIP 0000040
#define TARGET_INLCR 0000100
#define TARGET_IGNCR 0000200
#define TARGET_ICRNL 0000400
#define TARGET_IXON 0001000
#define TARGET_IXOFF 0002000
#define TARGET_IXANY 0004000
#define TARGET_IUCLC 0010000
#define TARGET_IMAXBEL 0020000
/* c_oflag bits */
#define TARGET_OPOST 0000001
#define TARGET_ONLCR 0000002
#define TARGET_OLCUC 0000004
#define TARGET_OCRNL 0000010
#define TARGET_ONOCR 0000020
#define TARGET_ONLRET 0000040
#define TARGET_OFILL 00000100
#define TARGET_OFDEL 00000200
#define TARGET_NLDLY 00001400
#define TARGET_NL0 00000000
#define TARGET_NL1 00000400
#define TARGET_NL2 00001000
#define TARGET_NL3 00001400
#define TARGET_TABDLY 00006000
#define TARGET_TAB0 00000000
#define TARGET_TAB1 00002000
#define TARGET_TAB2 00004000
#define TARGET_TAB3 00006000
#define TARGET_CRDLY 00030000
#define TARGET_CR0 00000000
#define TARGET_CR1 00010000
#define TARGET_CR2 00020000
#define TARGET_CR3 00030000
#define TARGET_FFDLY 00040000
#define TARGET_FF0 00000000
#define TARGET_FF1 00040000
#define TARGET_BSDLY 00100000
#define TARGET_BS0 00000000
#define TARGET_BS1 00100000
#define TARGET_VTDLY 00200000
#define TARGET_VT0 00000000
#define TARGET_VT1 00200000
#define TARGET_XTABS 01000000 /* Hmm.. Linux/i386 considers this part of TABDLY.. */
/* c_cflag bit meaning */
#define TARGET_CBAUD 0000377
#define TARGET_B0 0000000 /* hang up */
#define TARGET_B50 0000001
#define TARGET_B75 0000002
#define TARGET_B110 0000003
#define TARGET_B134 0000004
#define TARGET_B150 0000005
#define TARGET_B200 0000006
#define TARGET_B300 0000007
#define TARGET_B600 0000010
#define TARGET_B1200 0000011
#define TARGET_B1800 0000012
#define TARGET_B2400 0000013
#define TARGET_B4800 0000014
#define TARGET_B9600 0000015
#define TARGET_B19200 0000016
#define TARGET_B38400 0000017
#define TARGET_EXTA B19200
#define TARGET_EXTB B38400
#define TARGET_CBAUDEX 0000000
#define TARGET_B57600 00020
#define TARGET_B115200 00021
#define TARGET_B230400 00022
#define TARGET_B460800 00023
#define TARGET_B500000 00024
#define TARGET_B576000 00025
#define TARGET_B921600 00026
#define TARGET_B1000000 00027
#define TARGET_B1152000 00030
#define TARGET_B1500000 00031
#define TARGET_B2000000 00032
#define TARGET_B2500000 00033
#define TARGET_B3000000 00034
#define TARGET_B3500000 00035
#define TARGET_B4000000 00036
#define TARGET_CSIZE 00001400
#define TARGET_CS5 00000000
#define TARGET_CS6 00000400
#define TARGET_CS7 00001000
#define TARGET_CS8 00001400
#define TARGET_CSTOPB 00002000
#define TARGET_CREAD 00004000
#define TARGET_PARENB 00010000
#define TARGET_PARODD 00020000
#define TARGET_HUPCL 00040000
#define TARGET_CLOCAL 00100000
#define TARGET_CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
#define TARGET_ISIG 0x00000080
#define TARGET_ICANON 0x00000100
#define TARGET_XCASE 0x00004000
#define TARGET_ECHO 0x00000008
#define TARGET_ECHOE 0x00000002
#define TARGET_ECHOK 0x00000004
#define TARGET_ECHONL 0x00000010
#define TARGET_NOFLSH 0x80000000
#define TARGET_TOSTOP 0x00400000
#define TARGET_ECHOCTL 0x00000040
#define TARGET_ECHOPRT 0x00000020
#define TARGET_ECHOKE 0x00000001
#define TARGET_FLUSHO 0x00800000
#define TARGET_PENDIN 0x20000000
#define TARGET_IEXTEN 0x00000400
/* ioctls */
#define TARGET_FIOCLEX TARGET_IO('f', 1)
#define TARGET_FIONCLEX TARGET_IO('f', 2)
#define TARGET_FIOASYNC TARGET_IOW('f', 125, int)
#define TARGET_FIONBIO TARGET_IOW('f', 126, int)
#define TARGET_FIONREAD TARGET_IOR('f', 127, int)
#define TARGET_TIOCINQ TARGET_FIONREAD
//#define TARGET_FIOQSIZE TARGET_IOR('f', 128, loff_t)
#define TARGET_TCGETS TARGET_IOR('t', 19, struct target_termios)
#define TARGET_TCSETS TARGET_IOW('t', 20, struct target_termios)
#define TARGET_TCSETSW TARGET_IOW('t', 21, struct target_termios)
#define TARGET_TCSETSF TARGET_IOW('t', 22, struct target_termios)
#define TARGET_TCGETA TARGET_IOR('t', 23, struct target_termio)
#define TARGET_TCSETA TARGET_IOW('t', 24, struct target_termio)
#define TARGET_TCSETAW TARGET_IOW('t', 25, struct target_termio)
#define TARGET_TCSETAF TARGET_IOW('t', 28, struct target_termio)
#define TARGET_TCSBRK TARGET_IO('t', 29)
#define TARGET_TCXONC TARGET_IO('t', 30)
#define TARGET_TCFLSH TARGET_IO('t', 31)
#define TARGET_TIOCSWINSZ TARGET_IOW('t', 103, struct target_winsize)
#define TARGET_TIOCGWINSZ TARGET_IOR('t', 104, struct target_winsize)
#define TARGET_TIOCSTART TARGET_IO('t', 110) /* start output, like ^Q */
#define TARGET_TIOCSTOP TARGET_IO('t', 111) /* stop output, like ^S */
#define TARGET_TIOCOUTQ TARGET_IOR('t', 115, int) /* output queue size */
#define TARGET_TIOCGLTC TARGET_IOR('t', 116, struct target_ltchars)
#define TARGET_TIOCSLTC TARGET_IOW('t', 117, struct target_ltchars)
#define TARGET_TIOCSPGRP TARGET_IOW('t', 118, int)
#define TARGET_TIOCGPGRP TARGET_IOR('t', 119, int)
#define TARGET_TIOCEXCL 0x540C
#define TARGET_TIOCNXCL 0x540D
#define TARGET_TIOCSCTTY 0x540E
#define TARGET_TIOCSTI 0x5412
#define TARGET_TIOCMGET 0x5415
#define TARGET_TIOCMBIS 0x5416
#define TARGET_TIOCMBIC 0x5417
#define TARGET_TIOCMSET 0x5418
#define TARGET_TIOCGSOFTCAR 0x5419
#define TARGET_TIOCSSOFTCAR 0x541A
#define TARGET_TIOCLINUX 0x541C
#define TARGET_TIOCCONS 0x541D
#define TARGET_TIOCGSERIAL 0x541E
#define TARGET_TIOCSSERIAL 0x541F
#define TARGET_TIOCPKT 0x5420
#define TARGET_TIOCNOTTY 0x5422
#define TARGET_TIOCSETD 0x5423
#define TARGET_TIOCGETD 0x5424
#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */
#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */
#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */
#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */
#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */
#define TARGET_TIOCSERCONFIG 0x5453
#define TARGET_TIOCSERGWILD 0x5454
#define TARGET_TIOCSERSWILD 0x5455
#define TARGET_TIOCGLCKTRMIOS 0x5456
#define TARGET_TIOCSLCKTRMIOS 0x5457
#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
# define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */
#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */

View File

@@ -4,17 +4,11 @@
#include "thunk.h"
#include <signal.h>
#include <string.h>
#include "syscall_defs.h"
#if defined(TARGET_I386)
#include "cpu-i386.h"
#include "syscall-i386.h"
#elif defined(TARGET_ARM)
#include "cpu-arm.h"
#include "syscall-arm.h"
#else
#error unsupported target CPU
#endif
#include "cpu.h"
#include "syscall.h"
/* This struct is used to hold certain information about the image.
* Basically, it replicates in user space what would be certain
@@ -55,10 +49,21 @@ struct vm86_saved_state {
};
#endif
#ifdef TARGET_ARM
/* FPU emulator */
#include "nwfpe/fpa11.h"
#undef put_user
#undef get_user
#endif
/* NOTE: we force a big alignment so that the stack stored after is
aligned too */
typedef struct TaskState {
struct TaskState *next;
#ifdef TARGET_ARM
/* FPA state */
FPA11 fpa;
#endif
#ifdef TARGET_I386
struct target_vm86plus_struct *target_v86;
struct vm86_saved_state vm86_saved_regs;
@@ -116,4 +121,121 @@ long target_mremap(unsigned long old_addr, unsigned long old_size,
unsigned long new_addr);
int target_msync(unsigned long start, unsigned long len, int flags);
/* user access */
#define VERIFY_READ 0
#define VERIFY_WRITE 1
#define access_ok(type,addr,size) (1)
#define __put_user(x,ptr)\
({\
int size = sizeof(*ptr);\
switch(size) {\
case 1:\
stb(ptr, (typeof(*ptr))(x));\
break;\
case 2:\
stw(ptr, (typeof(*ptr))(x));\
break;\
case 4:\
stl(ptr, (typeof(*ptr))(x));\
break;\
case 8:\
stq(ptr, (typeof(*ptr))(x));\
break;\
default:\
abort();\
}\
0;\
})
#define __get_user(x, ptr) \
({\
int size = sizeof(*ptr);\
switch(size) {\
case 1:\
x = (typeof(*ptr))ldub((void *)ptr);\
break;\
case 2:\
x = (typeof(*ptr))lduw((void *)ptr);\
break;\
case 4:\
x = (typeof(*ptr))ldl((void *)ptr);\
break;\
case 8:\
x = (typeof(*ptr))ldq((void *)ptr);\
break;\
default:\
abort();\
}\
0;\
})
static inline unsigned long __copy_to_user(void *dst, const void *src,
unsigned long size)
{
memcpy(dst, src, size);
return 0;
}
static inline unsigned long __copy_from_user(void *dst, const void *src,
unsigned long size)
{
memcpy(dst, src, size);
return 0;
}
static inline unsigned long __clear_user(void *dst, unsigned long size)
{
memset(dst, 0, size);
return 0;
}
#define put_user(x,ptr)\
({\
int __ret;\
if (access_ok(VERIFY_WRITE, ptr, sizeof(*ptr)))\
__ret = __put_user(x, ptr);\
else\
__ret = -EFAULT;\
__ret;\
})
#define get_user(x,ptr)\
({\
int __ret;\
if (access_ok(VERIFY_READ, ptr, sizeof(*ptr)))\
__ret = __get_user(x, ptr);\
else\
__ret = -EFAULT;\
__ret;\
})
static inline unsigned long copy_to_user(void *dst, const void *src,
unsigned long size)
{
if (access_ok(VERIFY_WRITE, dst, size))
return __copy_to_user(dst, src, size);
else
return size;
}
static inline unsigned long copy_from_user(void *dst, const void *src,
unsigned long size)
{
if (access_ok(VERIFY_READ, src, size))
return __copy_from_user(dst, src, size);
else
return size;
}
static inline unsigned long clear_user(void *dst, unsigned long size)
{
if (access_ok(VERIFY_WRITE, dst, size))
return __clear_user(dst, size);
else
return size;
}
#endif

View File

@@ -67,7 +67,7 @@ static uint8_t host_to_target_signal_table[65] = {
[SIGILL] = TARGET_SIGILL,
[SIGTRAP] = TARGET_SIGTRAP,
[SIGABRT] = TARGET_SIGABRT,
[SIGIOT] = TARGET_SIGIOT,
/* [SIGIOT] = TARGET_SIGIOT,*/
[SIGBUS] = TARGET_SIGBUS,
[SIGFPE] = TARGET_SIGFPE,
[SIGKILL] = TARGET_SIGKILL,
@@ -109,7 +109,8 @@ static inline int target_to_host_signal(int sig)
return target_to_host_signal_table[sig];
}
void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
static void host_to_target_sigset_internal(target_sigset_t *d,
const sigset_t *s)
{
int i;
unsigned long sigmask;
@@ -122,25 +123,35 @@ void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
target_sigmask |= 1 << (host_to_target_signal(i + 1) - 1);
}
#if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32
d->sig[0] = tswapl(target_sigmask);
d->sig[0] = target_sigmask;
for(i = 1;i < TARGET_NSIG_WORDS; i++) {
d->sig[i] = tswapl(((unsigned long *)s)[i]);
d->sig[i] = ((unsigned long *)s)[i];
}
#elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2
d->sig[0] = tswapl(target_sigmask);
d->sig[1] = tswapl(sigmask >> 32);
d->sig[0] = target_sigmask;
d->sig[1] = sigmask >> 32;
#else
#error host_to_target_sigset
#endif
}
void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
{
target_sigset_t d1;
int i;
host_to_target_sigset_internal(&d1, s);
for(i = 0;i < TARGET_NSIG_WORDS; i++)
__put_user(d1.sig[i], &d->sig[i]);
}
void target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s)
{
int i;
unsigned long sigmask;
target_ulong target_sigmask;
target_sigmask = tswapl(s->sig[0]);
target_sigmask = s->sig[0];
sigmask = 0;
for(i = 0; i < 32; i++) {
if (target_sigmask & (1 << i))
@@ -149,15 +160,25 @@ void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
#if TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 32
((unsigned long *)d)[0] = sigmask;
for(i = 1;i < TARGET_NSIG_WORDS; i++) {
((unsigned long *)d)[i] = tswapl(s->sig[i]);
((unsigned long *)d)[i] = s->sig[i];
}
#elif TARGET_LONG_BITS == 32 && HOST_LONG_BITS == 64 && TARGET_NSIG_WORDS == 2
((unsigned long *)d)[0] = sigmask | (tswapl(s->sig[1]) << 32);
((unsigned long *)d)[0] = sigmask | ((unsigned long)(s->sig[1]) << 32);
#else
#error target_to_host_sigset
#endif /* TARGET_LONG_BITS */
}
void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
{
target_sigset_t s1;
int i;
for(i = 0;i < TARGET_NSIG_WORDS; i++)
__get_user(s1.sig[i], &s->sig[i]);
target_to_host_sigset_internal(d, &s1);
}
void host_to_target_old_sigset(target_ulong *old_sigset,
const sigset_t *sigset)
{
@@ -370,33 +391,6 @@ int queue_signal(int sig, target_siginfo_t *info)
}
}
#if defined(DEBUG_SIGNAL)
#ifdef __i386__
static void dump_regs(struct ucontext *uc)
{
fprintf(stderr,
"EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
"ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
"EFL=%08x EIP=%08x\n",
uc->uc_mcontext.gregs[EAX],
uc->uc_mcontext.gregs[EBX],
uc->uc_mcontext.gregs[ECX],
uc->uc_mcontext.gregs[EDX],
uc->uc_mcontext.gregs[ESI],
uc->uc_mcontext.gregs[EDI],
uc->uc_mcontext.gregs[EBP],
uc->uc_mcontext.gregs[ESP],
uc->uc_mcontext.gregs[EFL],
uc->uc_mcontext.gregs[EIP]);
}
#else
static void dump_regs(struct ucontext *uc)
{
}
#endif
#endif
static void host_signal_handler(int host_signum, siginfo_t *info,
void *puc)
{
@@ -405,7 +399,11 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
/* 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 (host_signum == SIGSEGV || host_signum == SIGBUS
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
|| host_signum == SIGFPE
#endif
) {
if (cpu_signal_handler(host_signum, info, puc))
return;
}
@@ -416,7 +414,6 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
return;
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "qemu: got signal %d\n", sig);
dump_regs(puc);
#endif
host_to_target_siginfo_noswap(&tinfo, info);
if (queue_signal(sig, &tinfo) == 1) {
@@ -429,11 +426,13 @@ int do_sigaction(int sig, const struct target_sigaction *act,
struct target_sigaction *oact)
{
struct emulated_sigaction *k;
struct sigaction act1;
int host_sig;
if (sig < 1 || sig > TARGET_NSIG)
return -EINVAL;
k = &sigact_table[sig - 1];
#if defined(DEBUG_SIGNAL) && 0
#if defined(DEBUG_SIGNAL)
fprintf(stderr, "sigaction sig=%d act=0x%08x, oact=0x%08x\n",
sig, (int)act, (int)oact);
#endif
@@ -448,73 +447,30 @@ int do_sigaction(int sig, const struct target_sigaction *act,
k->sa.sa_flags = tswapl(act->sa_flags);
k->sa.sa_restorer = tswapl(act->sa_restorer);
k->sa.sa_mask = act->sa_mask;
/* we update the host linux signal state */
host_sig = target_to_host_signal(sig);
if (host_sig != SIGSEGV && host_sig != SIGBUS) {
sigfillset(&act1.sa_mask);
act1.sa_flags = SA_SIGINFO;
if (k->sa.sa_flags & TARGET_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 == TARGET_SIG_IGN) {
act1.sa_sigaction = (void *)SIG_IGN;
} else if (k->sa._sa_handler == TARGET_SIG_DFL) {
act1.sa_sigaction = (void *)SIG_DFL;
} else {
act1.sa_sigaction = host_signal_handler;
}
sigaction(host_sig, &act1, NULL);
}
}
return 0;
}
#define __put_user(x,ptr)\
({\
int size = sizeof(*ptr);\
switch(size) {\
case 1:\
stb(ptr, (typeof(*ptr))(x));\
break;\
case 2:\
stw(ptr, (typeof(*ptr))(x));\
break;\
case 4:\
stl(ptr, (typeof(*ptr))(x));\
break;\
case 8:\
stq(ptr, (typeof(*ptr))(x));\
break;\
default:\
abort();\
}\
0;\
})
#define __get_user(x, ptr) \
({\
int size = sizeof(*ptr);\
switch(size) {\
case 1:\
x = (typeof(*ptr))ldub(ptr);\
break;\
case 2:\
x = (typeof(*ptr))lduw(ptr);\
break;\
case 4:\
x = (typeof(*ptr))ldl(ptr);\
break;\
case 8:\
x = (typeof(*ptr))ldq(ptr);\
break;\
default:\
abort();\
}\
0;\
})
#define __copy_to_user(dst, src, size)\
({\
memcpy(dst, src, size);\
0;\
})
#define __copy_from_user(dst, src, size)\
({\
memcpy(dst, src, size);\
0;\
})
#define __clear_user(dst, size)\
({\
memset(dst, 0, size);\
0;\
})
#ifndef offsetof
#define offsetof(type, field) ((size_t) &((type *)0)->field)
#endif
@@ -705,14 +661,12 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
target_sigset_t *set, CPUX86State *env)
{
struct sigframe *frame;
int err = 0;
int i, err = 0;
frame = get_sigframe(ka, env, sizeof(*frame));
#if 0
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
#endif
err |= __put_user((/*current->exec_domain
&& current->exec_domain->signal_invmap
&& sig < 32
@@ -726,12 +680,10 @@ static void setup_frame(int sig, struct emulated_sigaction *ka,
if (err)
goto give_sigsegv;
if (TARGET_NSIG_WORDS > 1) {
err |= __copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask));
}
if (err)
goto give_sigsegv;
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
if (__put_user(set->sig[i], &frame->extramask[i - 1]))
goto give_sigsegv;
}
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
@@ -771,14 +723,12 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
target_sigset_t *set, CPUX86State *env)
{
struct rt_sigframe *frame;
int err = 0;
int i, err = 0;
frame = get_sigframe(ka, env, sizeof(*frame));
#if 0
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
#endif
err |= __put_user((/*current->exec_domain
&& current->exec_domain->signal_invmap
@@ -801,9 +751,10 @@ static void setup_rt_frame(int sig, struct emulated_sigaction *ka,
err |= __put_user(/* current->sas_ss_size */ 0, &frame->uc.uc_stack.ss_size);
err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
env, set->sig[0]);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err)
goto give_sigsegv;
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
if (__put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i]))
goto give_sigsegv;
}
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
@@ -898,11 +849,14 @@ long do_sigreturn(CPUX86State *env)
fprintf(stderr, "do_sigreturn\n");
#endif
/* set blocked signals */
target_set.sig[0] = frame->sc.oldmask;
for(i = 1; i < TARGET_NSIG_WORDS; i++)
target_set.sig[i] = frame->extramask[i - 1];
if (__get_user(target_set.sig[0], &frame->sc.oldmask))
goto badframe;
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
if (__get_user(target_set.sig[i], &frame->extramask[i - 1]))
goto badframe;
}
target_to_host_sigset(&set, &target_set);
target_to_host_sigset_internal(&set, &target_set);
sigprocmask(SIG_SETMASK, &set, NULL);
/* restore registers */
@@ -918,7 +872,6 @@ badframe:
long do_rt_sigreturn(CPUX86State *env)
{
struct rt_sigframe *frame = (struct rt_sigframe *)(env->regs[R_ESP] - 4);
target_sigset_t target_set;
sigset_t set;
// stack_t st;
int eax;
@@ -927,9 +880,7 @@ long do_rt_sigreturn(CPUX86State *env)
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
#endif
memcpy(&target_set, &frame->uc.uc_sigmask, sizeof(target_sigset_t));
target_to_host_sigset(&set, &target_set);
target_to_host_sigset(&set, &frame->uc.uc_sigmask);
sigprocmask(SIG_SETMASK, &set, NULL);
if (restore_sigcontext(env, &frame->uc.uc_mcontext, &eax))
@@ -1153,13 +1104,13 @@ static void setup_frame(int usig, struct emulated_sigaction *ka,
target_sigset_t *set, CPUState *regs)
{
struct sigframe *frame = get_sigframe(ka, regs, sizeof(*frame));
int err = 0;
int i, err = 0;
err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);
if (TARGET_NSIG_WORDS > 1) {
err |= __copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask));
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
if (__put_user(set->sig[i], &frame->extramask[i - 1]))
return;
}
if (err == 0)
@@ -1172,12 +1123,11 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
target_sigset_t *set, CPUState *env)
{
struct rt_sigframe *frame = get_sigframe(ka, env, sizeof(*frame));
int err = 0;
int i, err = 0;
#if 0
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
return 1;
#endif
return /* 1 */;
__put_user_error(&frame->info, (target_ulong *)&frame->pinfo, err);
__put_user_error(&frame->uc, (target_ulong *)&frame->puc, err);
err |= copy_siginfo_to_user(&frame->info, info);
@@ -1187,7 +1137,10 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka,
err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/
env, set->sig[0]);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
if (__put_user(set->sig[i], &frame->uc.uc_sigmask.sig[i]))
return;
}
if (err == 0)
err = setup_return(env, ka, &frame->retcode, frame, usig);
@@ -1240,6 +1193,7 @@ long do_sigreturn(CPUState *env)
struct sigframe *frame;
target_sigset_t set;
sigset_t host_set;
int i;
/*
* Since we stacked the signal on a 64-bit boundary,
@@ -1255,13 +1209,14 @@ long do_sigreturn(CPUState *env)
if (verify_area(VERIFY_READ, frame, sizeof (*frame)))
goto badframe;
#endif
if (__get_user(set.sig[0], &frame->sc.oldmask)
|| (TARGET_NSIG_WORDS > 1
&& __copy_from_user(&set.sig[1], &frame->extramask,
sizeof(frame->extramask))))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.oldmask))
goto badframe;
for(i = 1; i < TARGET_NSIG_WORDS; i++) {
if (__get_user(set.sig[i], &frame->extramask[i - 1]))
goto badframe;
}
target_to_host_sigset(&host_set, &set);
target_to_host_sigset_internal(&host_set, &set);
sigprocmask(SIG_SETMASK, &host_set, NULL);
if (restore_sigcontext(env, &frame->sc))
@@ -1282,7 +1237,6 @@ badframe:
long do_rt_sigreturn(CPUState *env)
{
struct rt_sigframe *frame;
target_sigset_t set;
sigset_t host_set;
/*
@@ -1299,10 +1253,7 @@ long do_rt_sigreturn(CPUState *env)
if (verify_area(VERIFY_READ, frame, sizeof (*frame)))
goto badframe;
#endif
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe;
target_to_host_sigset(&host_set, &set);
target_to_host_sigset(&host_set, &frame->uc.uc_sigmask);
sigprocmask(SIG_SETMASK, &host_set, NULL);
if (restore_sigcontext(env, &frame->uc.uc_mcontext))
@@ -1405,7 +1356,7 @@ void process_pending_signals(void *cpu_env)
sigprocmask(SIG_BLOCK, &set, &old_set);
/* save the previous blocked signal state to restore it at the
end of the signal execution (see do_sigreturn) */
host_to_target_sigset(&target_old_set, &old_set);
host_to_target_sigset_internal(&target_old_set, &old_set);
/* if the CPU is in VM86 mode, we restore the 32 bit values */
#ifdef TARGET_I386

View File

@@ -0,0 +1,7 @@
struct target_pt_regs {
target_ulong psr;
target_ulong pc;
target_ulong npc;
target_ulong y;
target_ulong u_regs[16];
};

View File

@@ -0,0 +1,220 @@
#define TARGET_NR_exit 1 /* Common */
#define TARGET_NR_fork 2 /* Common */
#define TARGET_NR_read 3 /* Common */
#define TARGET_NR_write 4 /* Common */
#define TARGET_NR_open 5 /* Common */
#define TARGET_NR_close 6 /* Common */
#define TARGET_NR_wait4 7 /* Common */
#define TARGET_NR_creat 8 /* Common */
#define TARGET_NR_link 9 /* Common */
#define TARGET_NR_unlink 10 /* Common */
#define TARGET_NR_execv 11 /* SunOS Specific */
#define TARGET_NR_chdir 12 /* Common */
#define TARGET_NR_chown 13 /* Common */
#define TARGET_NR_mknod 14 /* Common */
#define TARGET_NR_chmod 15 /* Common */
#define TARGET_NR_lchown 16 /* Common */
#define TARGET_NR_brk 17 /* Common */
#define TARGET_NR_perfctr 18 /* Performance counter operations */
#define TARGET_NR_lseek 19 /* Common */
#define TARGET_NR_getpid 20 /* Common */
#define TARGET_NR_capget 21 /* Linux Specific */
#define TARGET_NR_capset 22 /* Linux Specific */
#define TARGET_NR_setuid 23 /* Implemented via setreuid in SunOS */
#define TARGET_NR_getuid 24 /* Common */
#define TARGET_NR_ptrace 26 /* Common */
#define TARGET_NR_alarm 27 /* Implemented via setitimer in SunOS */
#define TARGET_NR_sigaltstack 28 /* Common */
#define TARGET_NR_pause 29 /* Is sigblock(0)->sigpause() in SunOS */
#define TARGET_NR_utime 30 /* Implemented via utimes() under SunOS */
#define TARGET_NR_lchown32 31 /* Linux sparc32 specific */
#define TARGET_NR_fchown32 32 /* Linux sparc32 specific */
#define TARGET_NR_access 33 /* Common */
#define TARGET_NR_nice 34 /* Implemented via get/setpriority() in SunOS */
#define TARGET_NR_chown32 35 /* Linux sparc32 specific */
#define TARGET_NR_sync 36 /* Common */
#define TARGET_NR_kill 37 /* Common */
#define TARGET_NR_stat 38 /* Common */
#define TARGET_NR_sendfile 39 /* Linux Specific */
#define TARGET_NR_lstat 40 /* Common */
#define TARGET_NR_dup 41 /* Common */
#define TARGET_NR_pipe 42 /* Common */
#define TARGET_NR_times 43 /* Implemented via getrusage() in SunOS */
#define TARGET_NR_getuid32 44 /* Linux sparc32 specific */
#define TARGET_NR_umount2 45 /* Linux Specific */
#define TARGET_NR_setgid 46 /* Implemented via setregid() in SunOS */
#define TARGET_NR_getgid 47 /* Common */
#define TARGET_NR_signal 48 /* Implemented via sigvec() in SunOS */
#define TARGET_NR_geteuid 49 /* SunOS calls getuid() */
#define TARGET_NR_getegid 50 /* SunOS calls getgid() */
#define TARGET_NR_acct 51 /* Common */
#define TARGET_NR_getgid32 53 /* Linux sparc32 specific */
#define TARGET_NR_ioctl 54 /* Common */
#define TARGET_NR_reboot 55 /* Common */
#define TARGET_NR_mmap2 56 /* Linux sparc32 Specific */
#define TARGET_NR_symlink 57 /* Common */
#define TARGET_NR_readlink 58 /* Common */
#define TARGET_NR_execve 59 /* Common */
#define TARGET_NR_umask 60 /* Common */
#define TARGET_NR_chroot 61 /* Common */
#define TARGET_NR_fstat 62 /* Common */
#define TARGET_NR_fstat64 63 /* Linux sparc32 Specific */
#define TARGET_NR_getpagesize 64 /* Common */
#define TARGET_NR_msync 65 /* Common in newer 1.3.x revs... */
#define TARGET_NR_vfork 66 /* Common */
#define TARGET_NR_pread 67 /* Linux Specific */
#define TARGET_NR_pwrite 68 /* Linux Specific */
#define TARGET_NR_geteuid32 69 /* Linux sparc32, sbrk under SunOS */
#define TARGET_NR_getegid32 70 /* Linux sparc32, sstk under SunOS */
#define TARGET_NR_mmap 71 /* Common */
#define TARGET_NR_setreuid32 72 /* Linux sparc32, vadvise under SunOS */
#define TARGET_NR_munmap 73 /* Common */
#define TARGET_NR_mprotect 74 /* Common */
#define TARGET_NR_madvise 75 /* Common */
#define TARGET_NR_vhangup 76 /* Common */
#define TARGET_NR_truncate64 77 /* Linux sparc32 Specific */
#define TARGET_NR_mincore 78 /* Common */
#define TARGET_NR_getgroups 79 /* Common */
#define TARGET_NR_setgroups 80 /* Common */
#define TARGET_NR_getpgrp 81 /* Common */
#define TARGET_NR_setgroups32 82 /* Linux sparc32, setpgrp under SunOS */
#define TARGET_NR_setitimer 83 /* Common */
#define TARGET_NR_ftruncate64 84 /* Linux sparc32 Specific */
#define TARGET_NR_swapon 85 /* Common */
#define TARGET_NR_getitimer 86 /* Common */
#define TARGET_NR_setuid32 87 /* Linux sparc32, gethostname under SunOS */
#define TARGET_NR_sethostname 88 /* Common */
#define TARGET_NR_setgid32 89 /* Linux sparc32, getdtablesize under SunOS */
#define TARGET_NR_dup2 90 /* Common */
#define TARGET_NR_setfsuid32 91 /* Linux sparc32, getdopt under SunOS */
#define TARGET_NR_fcntl 92 /* Common */
#define TARGET_NR_select 93 /* Common */
#define TARGET_NR_setfsgid32 94 /* Linux sparc32, setdopt under SunOS */
#define TARGET_NR_fsync 95 /* Common */
#define TARGET_NR_setpriority 96 /* Common */
#define TARGET_NR_socket 97 /* Common */
#define TARGET_NR_connect 98 /* Common */
#define TARGET_NR_accept 99 /* Common */
#define TARGET_NR_getpriority 100 /* Common */
#define TARGET_NR_rt_sigreturn 101 /* Linux Specific */
#define TARGET_NR_rt_sigaction 102 /* Linux Specific */
#define TARGET_NR_rt_sigprocmask 103 /* Linux Specific */
#define TARGET_NR_rt_sigpending 104 /* Linux Specific */
#define TARGET_NR_rt_sigtimedwait 105 /* Linux Specific */
#define TARGET_NR_rt_sigqueueinfo 106 /* Linux Specific */
#define TARGET_NR_rt_sigsuspend 107 /* Linux Specific */
#define TARGET_NR_setresuid32 108 /* Linux Specific, sigvec under SunOS */
#define TARGET_NR_getresuid32 109 /* Linux Specific, sigblock under SunOS */
#define TARGET_NR_setresgid32 110 /* Linux Specific, sigsetmask under SunOS */
#define TARGET_NR_getresgid32 111 /* Linux Specific, sigpause under SunOS */
#define TARGET_NR_setregid32 112 /* Linux sparc32, sigstack under SunOS */
#define TARGET_NR_recvmsg 113 /* Common */
#define TARGET_NR_sendmsg 114 /* Common */
#define TARGET_NR_getgroups32 115 /* Linux sparc32, vtrace under SunOS */
#define TARGET_NR_gettimeofday 116 /* Common */
#define TARGET_NR_getrusage 117 /* Common */
#define TARGET_NR_getsockopt 118 /* Common */
#define TARGET_NR_getcwd 119 /* Linux Specific */
#define TARGET_NR_readv 120 /* Common */
#define TARGET_NR_writev 121 /* Common */
#define TARGET_NR_settimeofday 122 /* Common */
#define TARGET_NR_fchown 123 /* Common */
#define TARGET_NR_fchmod 124 /* Common */
#define TARGET_NR_recvfrom 125 /* Common */
#define TARGET_NR_setreuid 126 /* Common */
#define TARGET_NR_setregid 127 /* Common */
#define TARGET_NR_rename 128 /* Common */
#define TARGET_NR_truncate 129 /* Common */
#define TARGET_NR_ftruncate 130 /* Common */
#define TARGET_NR_flock 131 /* Common */
#define TARGET_NR_lstat64 132 /* Linux sparc32 Specific */
#define TARGET_NR_sendto 133 /* Common */
#define TARGET_NR_shutdown 134 /* Common */
#define TARGET_NR_socketpair 135 /* Common */
#define TARGET_NR_mkdir 136 /* Common */
#define TARGET_NR_rmdir 137 /* Common */
#define TARGET_NR_utimes 138 /* SunOS Specific */
#define TARGET_NR_stat64 139 /* Linux sparc32 Specific */
#define TARGET_NR_getpeername 141 /* Common */
#define TARGET_NR_gettid 143 /* ENOSYS under SunOS */
#define TARGET_NR_getrlimit 144 /* Common */
#define TARGET_NR_setrlimit 145 /* Common */
#define TARGET_NR_pivot_root 146 /* Linux Specific, killpg under SunOS */
#define TARGET_NR_prctl 147 /* ENOSYS under SunOS */
#define TARGET_NR_pciconfig_read 148 /* ENOSYS under SunOS */
#define TARGET_NR_pciconfig_write 149 /* ENOSYS under SunOS */
#define TARGET_NR_getsockname 150 /* Common */
#define TARGET_NR_poll 153 /* Common */
#define TARGET_NR_getdents64 154 /* Linux specific */
#define TARGET_NR_fcntl64 155 /* Linux sparc32 Specific */
#define TARGET_NR_statfs 157 /* Common */
#define TARGET_NR_fstatfs 158 /* Common */
#define TARGET_NR_umount 159 /* Common */
#define TARGET_NR_getdomainname 162 /* SunOS Specific */
#define TARGET_NR_setdomainname 163 /* Common */
#define TARGET_NR_quotactl 165 /* Common */
#define TARGET_NR_mount 167 /* Common */
#define TARGET_NR_ustat 168 /* Common */
#define TARGET_NR_getdents 174 /* Common */
#define TARGET_NR_setsid 175 /* Common */
#define TARGET_NR_fchdir 176 /* Common */
#define TARGET_NR_sigpending 183 /* Common */
#define TARGET_NR_query_module 184 /* Linux Specific */
#define TARGET_NR_setpgid 185 /* Common */
#define TARGET_NR_tkill 187 /* SunOS: fpathconf */
#define TARGET_NR_exit_group 188 /* Linux specific, sysconf undef SunOS */
#define TARGET_NR_uname 189 /* Linux Specific */
#define TARGET_NR_init_module 190 /* Linux Specific */
#define TARGET_NR_personality 191 /* Linux Specific */
#define TARGET_NR_getppid 197 /* Linux Specific */
#define TARGET_NR_sigaction 198 /* Linux Specific */
#define TARGET_NR_sgetmask 199 /* Linux Specific */
#define TARGET_NR_ssetmask 200 /* Linux Specific */
#define TARGET_NR_sigsuspend 201 /* Linux Specific */
#define TARGET_NR_oldlstat 202 /* Linux Specific */
#define TARGET_NR_uselib 203 /* Linux Specific */
#define TARGET_NR_readdir 204 /* Linux Specific */
#define TARGET_NR_readahead 205 /* Linux Specific */
#define TARGET_NR_socketcall 206 /* Linux Specific */
#define TARGET_NR_syslog 207 /* Linux Specific */
#define TARGET_NR_waitpid 212 /* Linux Specific */
#define TARGET_NR_swapoff 213 /* Linux Specific */
#define TARGET_NR_sysinfo 214 /* Linux Specific */
#define TARGET_NR_ipc 215 /* Linux Specific */
#define TARGET_NR_sigreturn 216 /* Linux Specific */
#define TARGET_NR_clone 217 /* Linux Specific */
#define TARGET_NR_adjtimex 219 /* Linux Specific */
#define TARGET_NR_sigprocmask 220 /* Linux Specific */
#define TARGET_NR_create_module 221 /* Linux Specific */
#define TARGET_NR_delete_module 222 /* Linux Specific */
#define TARGET_NR_get_kernel_syms 223 /* Linux Specific */
#define TARGET_NR_getpgid 224 /* Linux Specific */
#define TARGET_NR_bdflush 225 /* Linux Specific */
#define TARGET_NR_sysfs 226 /* Linux Specific */
#define TARGET_NR_afs_syscall 227 /* Linux Specific */
#define TARGET_NR_setfsuid 228 /* Linux Specific */
#define TARGET_NR_setfsgid 229 /* Linux Specific */
#define TARGET_NR__newselect 230 /* Linux Specific */
#define TARGET_NR_time 231 /* Linux Specific */
#define TARGET_NR_stime 233 /* Linux Specific */
#define TARGET_NR__llseek 236 /* Linux Specific */
#define TARGET_NR_mlock 237
#define TARGET_NR_munlock 238
#define TARGET_NR_mlockall 239
#define TARGET_NR_munlockall 240
#define TARGET_NR_sched_setparam 241
#define TARGET_NR_sched_getparam 242
#define TARGET_NR_sched_setscheduler 243
#define TARGET_NR_sched_getscheduler 244
#define TARGET_NR_sched_yield 245
#define TARGET_NR_sched_get_priority_max 246
#define TARGET_NR_sched_get_priority_min 247
#define TARGET_NR_sched_rr_get_interval 248
#define TARGET_NR_nanosleep 249
#define TARGET_NR_mremap 250
#define TARGET_NR__sysctl 251
#define TARGET_NR_getsid 252
#define TARGET_NR_fdatasync 253
#define TARGET_NR_nfsservctl 254
#define TARGET_NR_aplib 255
#define TARGET_NR__exit TARGET_NR_exit

279
linux-user/sparc/termbits.h Normal file
View File

@@ -0,0 +1,279 @@
/* from asm/termbits.h */
#define TARGET_NCCS 19
struct target_termios {
unsigned int c_iflag; /* input mode flags */
unsigned int c_oflag; /* output mode flags */
unsigned int c_cflag; /* control mode flags */
unsigned int c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[TARGET_NCCS]; /* control characters */
};
/* c_cc characters */
#define TARGET_VINTR 0
#define TARGET_VQUIT 1
#define TARGET_VERASE 2
#define TARGET_VKILL 3
#define TARGET_VEOF 4
#define TARGET_VEOL 5
#define TARGET_VEOL2 6
#define TARGET_VSWTC 7
#define TARGET_VSTART 8
#define TARGET_VSTOP 9
#define TARGET_VSUSP 10
#define TARGET_VDSUSP 11 /* SunOS POSIX nicety I do believe... */
#define TARGET_VREPRINT 12
#define TARGET_VDISCARD 13
#define TARGET_VWERASE 14
#define TARGET_VLNEXT 15
/* Kernel keeps vmin/vtime separated, user apps assume vmin/vtime is
* shared with eof/eol
*/
#define TARGET_VMIN TARGET_VEOF
#define TARGET_VTIME TARGET_VEOL
/* c_iflag bits */
#define TARGET_IGNBRK 0x00000001
#define TARGET_BRKINT 0x00000002
#define TARGET_IGNPAR 0x00000004
#define TARGET_PARMRK 0x00000008
#define TARGET_INPCK 0x00000010
#define TARGET_ISTRIP 0x00000020
#define TARGET_INLCR 0x00000040
#define TARGET_IGNCR 0x00000080
#define TARGET_ICRNL 0x00000100
#define TARGET_IUCLC 0x00000200
#define TARGET_IXON 0x00000400
#define TARGET_IXANY 0x00000800
#define TARGET_IXOFF 0x00001000
#define TARGET_IMAXBEL 0x00002000
/* c_oflag bits */
#define TARGET_OPOST 0x00000001
#define TARGET_OLCUC 0x00000002
#define TARGET_ONLCR 0x00000004
#define TARGET_OCRNL 0x00000008
#define TARGET_ONOCR 0x00000010
#define TARGET_ONLRET 0x00000020
#define TARGET_OFILL 0x00000040
#define TARGET_OFDEL 0x00000080
#define TARGET_NLDLY 0x00000100
#define TARGET_NL0 0x00000000
#define TARGET_NL1 0x00000100
#define TARGET_CRDLY 0x00000600
#define TARGET_CR0 0x00000000
#define TARGET_CR1 0x00000200
#define TARGET_CR2 0x00000400
#define TARGET_CR3 0x00000600
#define TARGET_TABDLY 0x00001800
#define TARGET_TAB0 0x00000000
#define TARGET_TAB1 0x00000800
#define TARGET_TAB2 0x00001000
#define TARGET_TAB3 0x00001800
#define TARGET_XTABS 0x00001800
#define TARGET_BSDLY 0x00002000
#define TARGET_BS0 0x00000000
#define TARGET_BS1 0x00002000
#define TARGET_VTDLY 0x00004000
#define TARGET_VT0 0x00000000
#define TARGET_VT1 0x00004000
#define TARGET_FFDLY 0x00008000
#define TARGET_FF0 0x00000000
#define TARGET_FF1 0x00008000
#define TARGET_PAGEOUT 0x00010000 /* SUNOS specific */
#define TARGET_WRAP 0x00020000 /* SUNOS specific */
/* c_cflag bit meaning */
#define TARGET_CBAUD 0x0000100f
#define TARGET_B0 0x00000000 /* hang up */
#define TARGET_B50 0x00000001
#define TARGET_B75 0x00000002
#define TARGET_B110 0x00000003
#define TARGET_B134 0x00000004
#define TARGET_B150 0x00000005
#define TARGET_B200 0x00000006
#define TARGET_B300 0x00000007
#define TARGET_B600 0x00000008
#define TARGET_B1200 0x00000009
#define TARGET_B1800 0x0000000a
#define TARGET_B2400 0x0000000b
#define TARGET_B4800 0x0000000c
#define TARGET_B9600 0x0000000d
#define TARGET_B19200 0x0000000e
#define TARGET_B38400 0x0000000f
#define TARGET_EXTA B19200
#define TARGET_EXTB B38400
#define TARGET_CSIZE 0x00000030
#define TARGET_CS5 0x00000000
#define TARGET_CS6 0x00000010
#define TARGET_CS7 0x00000020
#define TARGET_CS8 0x00000030
#define TARGET_CSTOPB 0x00000040
#define TARGET_CREAD 0x00000080
#define TARGET_PARENB 0x00000100
#define TARGET_PARODD 0x00000200
#define TARGET_HUPCL 0x00000400
#define TARGET_CLOCAL 0x00000800
#define TARGET_CBAUDEX 0x00001000
/* We'll never see these speeds with the Zilogs, but for completeness... */
#define TARGET_B57600 0x00001001
#define TARGET_B115200 0x00001002
#define TARGET_B230400 0x00001003
#define TARGET_B460800 0x00001004
/* This is what we can do with the Zilogs. */
#define TARGET_B76800 0x00001005
/* This is what we can do with the SAB82532. */
#define TARGET_B153600 0x00001006
#define TARGET_B307200 0x00001007
#define TARGET_B614400 0x00001008
#define TARGET_B921600 0x00001009
/* And these are the rest... */
#define TARGET_B500000 0x0000100a
#define TARGET_B576000 0x0000100b
#define TARGET_B1000000 0x0000100c
#define TARGET_B1152000 0x0000100d
#define TARGET_B1500000 0x0000100e
#define TARGET_B2000000 0x0000100f
/* These have totally bogus values and nobody uses them
so far. Later on we'd have to use say 0x10000x and
adjust CBAUD constant and drivers accordingly.
#define B2500000 0x00001010
#define B3000000 0x00001011
#define B3500000 0x00001012
#define B4000000 0x00001013 */
#define TARGET_CIBAUD 0x100f0000 /* input baud rate (not used) */
#define TARGET_CMSPAR 0x40000000 /* mark or space (stick) parity */
#define TARGET_CRTSCTS 0x80000000 /* flow control */
/* c_lflag bits */
#define TARGET_ISIG 0x00000001
#define TARGET_ICANON 0x00000002
#define TARGET_XCASE 0x00000004
#define TARGET_ECHO 0x00000008
#define TARGET_ECHOE 0x00000010
#define TARGET_ECHOK 0x00000020
#define TARGET_ECHONL 0x00000040
#define TARGET_NOFLSH 0x00000080
#define TARGET_TOSTOP 0x00000100
#define TARGET_ECHOCTL 0x00000200
#define TARGET_ECHOPRT 0x00000400
#define TARGET_ECHOKE 0x00000800
#define TARGET_DEFECHO 0x00001000 /* SUNOS thing, what is it? */
#define TARGET_FLUSHO 0x00002000
#define TARGET_PENDIN 0x00004000
#define TARGET_IEXTEN 0x00008000
/* ioctls */
/* Big T */
#define TARGET_TCGETA TARGET_IOR('T', 1, struct target_termio)
#define TARGET_TCSETA TARGET_IOW('T', 2, struct target_termio)
#define TARGET_TCSETAW TARGET_IOW('T', 3, struct target_termio)
#define TARGET_TCSETAF TARGET_IOW('T', 4, struct target_termio)
#define TARGET_TCSBRK TARGET_IO('T', 5)
#define TARGET_TCXONC TARGET_IO('T', 6)
#define TARGET_TCFLSH TARGET_IO('T', 7)
#define TARGET_TCGETS TARGET_IOR('T', 8, struct target_termios)
#define TARGET_TCSETS TARGET_IOW('T', 9, struct target_termios)
#define TARGET_TCSETSW TARGET_IOW('T', 10, struct target_termios)
#define TARGET_TCSETSF TARGET_IOW('T', 11, struct target_termios)
/* Note that all the ioctls that are not available in Linux have a
* double underscore on the front to: a) avoid some programs to
* thing we support some ioctls under Linux (autoconfiguration stuff)
*/
/* Little t */
#define TARGET_TIOCGETD TARGET_IOR('t', 0, int)
#define TARGET_TIOCSETD TARGET_IOW('t', 1, int)
//#define __TIOCHPCL _IO('t', 2) /* SunOS Specific */
//#define __TIOCMODG _IOR('t', 3, int) /* SunOS Specific */
//#define __TIOCMODS _IOW('t', 4, int) /* SunOS Specific */
//#define __TIOCGETP _IOR('t', 8, struct sgttyb) /* SunOS Specific */
//#define __TIOCSETP _IOW('t', 9, struct sgttyb) /* SunOS Specific */
//#define __TIOCSETN _IOW('t', 10, struct sgttyb) /* SunOS Specific */
#define TARGET_TIOCEXCL TARGET_IO('t', 13)
#define TARGET_TIOCNXCL TARGET_IO('t', 14)
//#define __TIOCFLUSH _IOW('t', 16, int) /* SunOS Specific */
//#define __TIOCSETC _IOW('t', 17, struct tchars) /* SunOS Specific */
//#define __TIOCGETC _IOR('t', 18, struct tchars) /* SunOS Specific */
//#define __TIOCTCNTL _IOW('t', 32, int) /* SunOS Specific */
//#define __TIOCSIGNAL _IOW('t', 33, int) /* SunOS Specific */
//#define __TIOCSETX _IOW('t', 34, int) /* SunOS Specific */
//#define __TIOCGETX _IOR('t', 35, int) /* SunOS Specific */
#define TARGET_TIOCCONS TARGET_IO('t', 36)
//#define __TIOCSSIZE _IOW('t', 37, struct sunos_ttysize) /* SunOS Specific */
//#define __TIOCGSIZE _IOR('t', 38, struct sunos_ttysize) /* SunOS Specific */
#define TARGET_TIOCGSOFTCAR TARGET_IOR('t', 100, int)
#define TARGET_TIOCSSOFTCAR TARGET_IOW('t', 101, int)
//#define __TIOCUCNTL _IOW('t', 102, int) /* SunOS Specific */
#define TARGET_TIOCSWINSZ TARGET_IOW('t', 103, struct winsize)
#define TARGET_TIOCGWINSZ TARGET_IOR('t', 104, struct winsize)
//#define __TIOCREMOTE _IOW('t', 105, int) /* SunOS Specific */
#define TARGET_TIOCMGET TARGET_IOR('t', 106, int)
#define TARGET_TIOCMBIC TARGET_IOW('t', 107, int)
#define TARGET_TIOCMBIS TARGET_IOW('t', 108, int)
#define TARGET_TIOCMSET TARGET_IOW('t', 109, int)
#define TARGET_TIOCSTART TARGET_IO('t', 110)
#define TARGET_TIOCSTOP TARGET_IO('t', 111)
#define TARGET_TIOCPKT TARGET_IOW('t', 112, int)
#define TARGET_TIOCNOTTY TARGET_IO('t', 113)
#define TARGET_TIOCSTI TARGET_IOW('t', 114, char)
#define TARGET_TIOCOUTQ TARGET_IOR('t', 115, int)
//#define __TIOCGLTC _IOR('t', 116, struct ltchars) /* SunOS Specific */
//#define __TIOCSLTC _IOW('t', 117, struct ltchars) /* SunOS Specific */
/* 118 is the non-posix setpgrp tty ioctl */
/* 119 is the non-posix getpgrp tty ioctl */
//#define __TIOCCDTR TARGET_IO('t', 120) /* SunOS Specific */
//#define __TIOCSDTR TARGET_IO('t', 121) /* SunOS Specific */
#define TARGET_TIOCCBRK TARGET_IO('t', 122)
#define TARGET_TIOCSBRK TARGET_IO('t', 123)
//#define __TIOCLGET TARGET_IOW('t', 124, int) /* SunOS Specific */
//#define __TIOCLSET TARGET_IOW('t', 125, int) /* SunOS Specific */
//#define __TIOCLBIC TARGET_IOW('t', 126, int) /* SunOS Specific */
//#define __TIOCLBIS TARGET_IOW('t', 127, int) /* SunOS Specific */
//#define __TIOCISPACE TARGET_IOR('t', 128, int) /* SunOS Specific */
//#define __TIOCISIZE TARGET_IOR('t', 129, int) /* SunOS Specific */
#define TARGET_TIOCSPGRP TARGET_IOW('t', 130, int)
#define TARGET_TIOCGPGRP TARGET_IOR('t', 131, int)
#define TARGET_TIOCSCTTY TARGET_IO('t', 132)
#define TARGET_TIOCGSID TARGET_IOR('t', 133, int)
/* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */
#define TARGET_TIOCGPTN TARGET_IOR('t', 134, unsigned int) /* Get Pty Number */
#define TARGET_TIOCSPTLCK TARGET_IOW('t', 135, int) /* Lock/unlock PTY */
/* Little f */
#define TARGET_FIOCLEX TARGET_IO('f', 1)
#define TARGET_FIONCLEX TARGET_IO('f', 2)
#define TARGET_FIOASYNC TARGET_IOW('f', 125, int)
#define TARGET_FIONBIO TARGET_IOW('f', 126, int)
#define TARGET_FIONREAD TARGET_IOR('f', 127, int)
#define TARGET_TIOCINQ TARGET_FIONREAD
/* SCARY Rutgers local SunOS kernel hackery, perhaps I will support it
* someday. This is completely bogus, I know...
*/
//#define __TCGETSTAT TARGET_IO('T', 200) /* Rutgers specific */
//#define __TCSETSTAT TARGET_IO('T', 201) /* Rutgers specific */
/* Linux specific, no SunOS equivalent. */
#define TARGET_TIOCLINUX 0x541C
#define TARGET_TIOCGSERIAL 0x541E
#define TARGET_TIOCSSERIAL 0x541F
#define TARGET_TCSBRKP 0x5425
#define TARGET_TIOCTTYGSTRUCT 0x5426
#define TARGET_TIOCSERCONFIG 0x5453
#define TARGET_TIOCSERGWILD 0x5454
#define TARGET_TIOCSERSWILD 0x5455
#define TARGET_TIOCGLCKTRMIOS 0x5456
#define TARGET_TIOCSLCKTRMIOS 0x5457
#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
#define TARGET_TIOCMIWAIT 0x545C /* Wait input */
#define TARGET_TIOCGICOUNT 0x545D /* Read serial port inline interrupt counts */

File diff suppressed because it is too large Load Diff

View File

@@ -4,284 +4,7 @@
most of them stay the same, so we handle it by puting ifdefs if
necessary */
#define TARGET_NR_exit 1
#define TARGET_NR_fork 2
#define TARGET_NR_read 3
#define TARGET_NR_write 4
#define TARGET_NR_open 5
#define TARGET_NR_close 6
#define TARGET_NR_waitpid 7
#define TARGET_NR_creat 8
#define TARGET_NR_link 9
#define TARGET_NR_unlink 10
#define TARGET_NR_execve 11
#define TARGET_NR_chdir 12
#define TARGET_NR_time 13
#define TARGET_NR_mknod 14
#define TARGET_NR_chmod 15
#define TARGET_NR_lchown 16
#define TARGET_NR_break 17
#define TARGET_NR_oldstat 18
#define TARGET_NR_lseek 19
#define TARGET_NR_getpid 20
#define TARGET_NR_mount 21
#define TARGET_NR_umount 22
#define TARGET_NR_setuid 23
#define TARGET_NR_getuid 24
#define TARGET_NR_stime 25
#define TARGET_NR_ptrace 26
#define TARGET_NR_alarm 27
#define TARGET_NR_oldfstat 28
#define TARGET_NR_pause 29
#define TARGET_NR_utime 30
#define TARGET_NR_stty 31
#define TARGET_NR_gtty 32
#define TARGET_NR_access 33
#define TARGET_NR_nice 34
#define TARGET_NR_ftime 35
#define TARGET_NR_sync 36
#define TARGET_NR_kill 37
#define TARGET_NR_rename 38
#define TARGET_NR_mkdir 39
#define TARGET_NR_rmdir 40
#define TARGET_NR_dup 41
#define TARGET_NR_pipe 42
#define TARGET_NR_times 43
#define TARGET_NR_prof 44
#define TARGET_NR_brk 45
#define TARGET_NR_setgid 46
#define TARGET_NR_getgid 47
#define TARGET_NR_signal 48
#define TARGET_NR_geteuid 49
#define TARGET_NR_getegid 50
#define TARGET_NR_acct 51
#define TARGET_NR_umount2 52
#define TARGET_NR_lock 53
#define TARGET_NR_ioctl 54
#define TARGET_NR_fcntl 55
#define TARGET_NR_mpx 56
#define TARGET_NR_setpgid 57
#define TARGET_NR_ulimit 58
#define TARGET_NR_oldolduname 59
#define TARGET_NR_umask 60
#define TARGET_NR_chroot 61
#define TARGET_NR_ustat 62
#define TARGET_NR_dup2 63
#define TARGET_NR_getppid 64
#define TARGET_NR_getpgrp 65
#define TARGET_NR_setsid 66
#define TARGET_NR_sigaction 67
#define TARGET_NR_sgetmask 68
#define TARGET_NR_ssetmask 69
#define TARGET_NR_setreuid 70
#define TARGET_NR_setregid 71
#define TARGET_NR_sigsuspend 72
#define TARGET_NR_sigpending 73
#define TARGET_NR_sethostname 74
#define TARGET_NR_setrlimit 75
#define TARGET_NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
#define TARGET_NR_getrusage 77
#define TARGET_NR_gettimeofday 78
#define TARGET_NR_settimeofday 79
#define TARGET_NR_getgroups 80
#define TARGET_NR_setgroups 81
#define TARGET_NR_select 82
#define TARGET_NR_symlink 83
#define TARGET_NR_oldlstat 84
#define TARGET_NR_readlink 85
#define TARGET_NR_uselib 86
#define TARGET_NR_swapon 87
#define TARGET_NR_reboot 88
#define TARGET_NR_readdir 89
#define TARGET_NR_mmap 90
#define TARGET_NR_munmap 91
#define TARGET_NR_truncate 92
#define TARGET_NR_ftruncate 93
#define TARGET_NR_fchmod 94
#define TARGET_NR_fchown 95
#define TARGET_NR_getpriority 96
#define TARGET_NR_setpriority 97
#define TARGET_NR_profil 98
#define TARGET_NR_statfs 99
#define TARGET_NR_fstatfs 100
#define TARGET_NR_ioperm 101
#define TARGET_NR_socketcall 102
#define TARGET_NR_syslog 103
#define TARGET_NR_setitimer 104
#define TARGET_NR_getitimer 105
#define TARGET_NR_stat 106
#define TARGET_NR_lstat 107
#define TARGET_NR_fstat 108
#define TARGET_NR_olduname 109
#define TARGET_NR_iopl 110
#define TARGET_NR_vhangup 111
#define TARGET_NR_idle 112
#define TARGET_NR_vm86old 113
#define TARGET_NR_wait4 114
#define TARGET_NR_swapoff 115
#define TARGET_NR_sysinfo 116
#define TARGET_NR_ipc 117
#define TARGET_NR_fsync 118
#define TARGET_NR_sigreturn 119
#define TARGET_NR_clone 120
#define TARGET_NR_setdomainname 121
#define TARGET_NR_uname 122
#define TARGET_NR_modify_ldt 123
#define TARGET_NR_adjtimex 124
#define TARGET_NR_mprotect 125
#define TARGET_NR_sigprocmask 126
#define TARGET_NR_create_module 127
#define TARGET_NR_init_module 128
#define TARGET_NR_delete_module 129
#define TARGET_NR_get_kernel_syms 130
#define TARGET_NR_quotactl 131
#define TARGET_NR_getpgid 132
#define TARGET_NR_fchdir 133
#define TARGET_NR_bdflush 134
#define TARGET_NR_sysfs 135
#define TARGET_NR_personality 136
#define TARGET_NR_afs_syscall 137 /* Syscall for Andrew File System */
#define TARGET_NR_setfsuid 138
#define TARGET_NR_setfsgid 139
#define TARGET_NR__llseek 140
#define TARGET_NR_getdents 141
#define TARGET_NR__newselect 142
#define TARGET_NR_flock 143
#define TARGET_NR_msync 144
#define TARGET_NR_readv 145
#define TARGET_NR_writev 146
#define TARGET_NR_getsid 147
#define TARGET_NR_fdatasync 148
#define TARGET_NR__sysctl 149
#define TARGET_NR_mlock 150
#define TARGET_NR_munlock 151
#define TARGET_NR_mlockall 152
#define TARGET_NR_munlockall 153
#define TARGET_NR_sched_setparam 154
#define TARGET_NR_sched_getparam 155
#define TARGET_NR_sched_setscheduler 156
#define TARGET_NR_sched_getscheduler 157
#define TARGET_NR_sched_yield 158
#define TARGET_NR_sched_get_priority_max 159
#define TARGET_NR_sched_get_priority_min 160
#define TARGET_NR_sched_rr_get_interval 161
#define TARGET_NR_nanosleep 162
#define TARGET_NR_mremap 163
#define TARGET_NR_setresuid 164
#define TARGET_NR_getresuid 165
#define TARGET_NR_vm86 166
#define TARGET_NR_query_module 167
#define TARGET_NR_poll 168
#define TARGET_NR_nfsservctl 169
#define TARGET_NR_setresgid 170
#define TARGET_NR_getresgid 171
#define TARGET_NR_prctl 172
#define TARGET_NR_rt_sigreturn 173
#define TARGET_NR_rt_sigaction 174
#define TARGET_NR_rt_sigprocmask 175
#define TARGET_NR_rt_sigpending 176
#define TARGET_NR_rt_sigtimedwait 177
#define TARGET_NR_rt_sigqueueinfo 178
#define TARGET_NR_rt_sigsuspend 179
#define TARGET_NR_pread 180
#define TARGET_NR_pwrite 181
#define TARGET_NR_chown 182
#define TARGET_NR_getcwd 183
#define TARGET_NR_capget 184
#define TARGET_NR_capset 185
#define TARGET_NR_sigaltstack 186
#define TARGET_NR_sendfile 187
#define TARGET_NR_getpmsg 188 /* some people actually want streams */
#define TARGET_NR_putpmsg 189 /* some people actually want streams */
#define TARGET_NR_vfork 190
#define TARGET_NR_ugetrlimit 191 /* SuS compliant getrlimit */
#define TARGET_NR_mmap2 192
#define TARGET_NR_truncate64 193
#define TARGET_NR_ftruncate64 194
#define TARGET_NR_stat64 195
#define TARGET_NR_lstat64 196
#define TARGET_NR_fstat64 197
#define TARGET_NR_lchown32 198
#define TARGET_NR_getuid32 199
#define TARGET_NR_getgid32 200
#define TARGET_NR_geteuid32 201
#define TARGET_NR_getegid32 202
#define TARGET_NR_setreuid32 203
#define TARGET_NR_setregid32 204
#define TARGET_NR_getgroups32 205
#define TARGET_NR_setgroups32 206
#define TARGET_NR_fchown32 207
#define TARGET_NR_setresuid32 208
#define TARGET_NR_getresuid32 209
#define TARGET_NR_setresgid32 210
#define TARGET_NR_getresgid32 211
#define TARGET_NR_chown32 212
#define TARGET_NR_setuid32 213
#define TARGET_NR_setgid32 214
#define TARGET_NR_setfsuid32 215
#define TARGET_NR_setfsgid32 216
#if defined(TARGET_I386)
#define TARGET_NR_pivot_root 217
#define TARGET_NR_mincore 218
#define TARGET_NR_madvise 219
#define TARGET_NR_madvise1 219 /* delete when C lib stub is removed */
#define TARGET_NR_getdents64 220
#endif
#if defined(TARGET_ARM)
#define TARGET_NR_getdents64 217
#define TARGET_NR_pivot_root 218
#define TARGET_NR_mincore 219
#define TARGET_NR_madvise 220
#endif
#define TARGET_NR_fcntl64 221
#define TARGET_NR_security 223 /* syscall for security modules */
#define TARGET_NR_gettid 224
#define TARGET_NR_readahead 225
#define TARGET_NR_setxattr 226
#define TARGET_NR_lsetxattr 227
#define TARGET_NR_fsetxattr 228
#define TARGET_NR_getxattr 229
#define TARGET_NR_lgetxattr 230
#define TARGET_NR_fgetxattr 231
#define TARGET_NR_listxattr 232
#define TARGET_NR_llistxattr 233
#define TARGET_NR_flistxattr 234
#define TARGET_NR_removexattr 235
#define TARGET_NR_lremovexattr 236
#define TARGET_NR_fremovexattr 237
#define TARGET_NR_tkill 238
#define TARGET_NR_sendfile64 239
#define TARGET_NR_futex 240
#define TARGET_NR_sched_setaffinity 241
#define TARGET_NR_sched_getaffinity 242
#define TARGET_NR_set_thread_area 243
#define TARGET_NR_get_thread_area 244
#define TARGET_NR_io_setup 245
#define TARGET_NR_io_destroy 246
#define TARGET_NR_io_getevents 247
#define TARGET_NR_io_submit 248
#define TARGET_NR_io_cancel 249
#define TARGET_NR_fadvise64 250
#define TARGET_NR_exit_group 252
#define TARGET_NR_lookup_dcookie 253
#define TARGET_NR_epoll_create 254
#define TARGET_NR_epoll_ctl 255
#define TARGET_NR_epoll_wait 256
#define TARGET_NR_remap_file_pages 257
#define TARGET_NR_set_tid_address 258
#define TARGET_NR_timer_create 259
#define TARGET_NR_timer_settime (TARGET_NR_timer_create+1)
#define TARGET_NR_timer_gettime (TARGET_NR_timer_create+2)
#define TARGET_NR_timer_getoverrun (TARGET_NR_timer_create+3)
#define TARGET_NR_timer_delete (TARGET_NR_timer_create+4)
#define TARGET_NR_clock_settime (TARGET_NR_timer_create+5)
#define TARGET_NR_clock_gettime (TARGET_NR_timer_create+6)
#define TARGET_NR_clock_getres (TARGET_NR_timer_create+7)
#define TARGET_NR_clock_nanosleep (TARGET_NR_timer_create+8)
#include "syscall_nr.h"
#define SOCKOP_socket 1
#define SOCKOP_bind 2
@@ -301,6 +24,19 @@
#define SOCKOP_sendmsg 16
#define SOCKOP_recvmsg 17
#define IPCOP_semop 1
#define IPCOP_semget 2
#define IPCOP_semctl 3
#define IPCOP_semtimedop 4
#define IPCOP_msgsnd 11
#define IPCOP_msgrcv 12
#define IPCOP_msgget 13
#define IPCOP_msgctl 14
#define IPCOP_shmat 21
#define IPCOP_shmdt 22
#define IPCOP_shmget 23
#define IPCOP_shmctl 24
/*
* The following is for compatibility across the various Linux
* platforms. The i386 ioctl numbering scheme doesn't really enforce
@@ -321,7 +57,7 @@
#define TARGET_IOC_WRITE 1U
#define TARGET_IOC_READ 2U
#elif defined(TARGET_PPC) || defined(TARGET_ALPHA)
#elif defined(TARGET_PPC) || defined(TARGET_ALPHA) || defined(TARGET_SPARC)
#define TARGET_IOC_SIZEBITS 13
#define TARGET_IOC_DIRBITS 3
@@ -392,6 +128,11 @@ struct target_tms {
target_clock_t tms_cstime;
};
struct target_utimbuf {
target_long actime;
target_long modtime;
};
struct target_sel_arg_struct {
target_long n;
target_long inp, outp, exp;
@@ -551,7 +292,7 @@ struct target_sigaction;
int do_sigaction(int sig, const struct target_sigaction *act,
struct target_sigaction *oact);
#if defined(TARGET_I386) || defined(TARGET_ARM)
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_PPC)
#define TARGET_SA_NOCLDSTOP 0x00000001
#define TARGET_SA_NOCLDWAIT 0x00000002 /* not supported yet */
@@ -686,7 +427,14 @@ typedef struct target_siginfo {
/*
* SIGILL si_codes
*/
#define TARGET_ILL_ILLOPC (1) /* illegal opcode */
#define TARGET_ILL_ILLOPN (2) /* illegal operand */
#define TARGET_ILL_ILLADR (3) /* illegal addressing mode */
#define TARGET_ILL_ILLTRP (4) /* illegal trap */
#define TARGET_ILL_PRVOPC (5) /* privileged opcode */
#define TARGET_ILL_PRVREG (6) /* privileged register */
#define TARGET_ILL_COPROC (7) /* coprocessor error */
#define TARGET_ILL_BADSTK (8) /* internal stack error */
/*
* SIGFPE si_codes
@@ -707,6 +455,13 @@ typedef struct target_siginfo {
#define TARGET_SEGV_MAPERR (1) /* address not mapped to object */
#define TARGET_SEGV_ACCERR (2) /* invalid permissions for mapped object */
/*
* SIGBUS si_codes
*/
#define TARGET_BUS_ADRALN (1) /* invalid address alignment */
#define TARGET_BUS_ADRERR (2) /* non-existant physical address */
#define TARGET_BUS_OBJERR (3) /* object specific hardware error */
/*
* SIGTRAP si_codes
*/
@@ -936,220 +691,26 @@ struct target_pollfd {
#define TARGET_HDIO_SET_PIO_MODE 0x0327 /* reconfig interface to new speed */
#if defined(TARGET_I386) || defined(TARGET_ARM)
/* 0x54 is just a magic number to make these relatively unique ('T') */
#define TARGET_TCGETS 0x5401
#define TARGET_TCSETS 0x5402
#define TARGET_TCSETSW 0x5403
#define TARGET_TCSETSF 0x5404
#define TARGET_TCGETA 0x5405
#define TARGET_TCSETA 0x5406
#define TARGET_TCSETAW 0x5407
#define TARGET_TCSETAF 0x5408
#define TARGET_TCSBRK 0x5409
#define TARGET_TCXONC 0x540A
#define TARGET_TCFLSH 0x540B
#define TARGET_TIOCEXCL 0x540C
#define TARGET_TIOCNXCL 0x540D
#define TARGET_TIOCSCTTY 0x540E
#define TARGET_TIOCGPGRP 0x540F
#define TARGET_TIOCSPGRP 0x5410
#define TARGET_TIOCOUTQ 0x5411
#define TARGET_TIOCSTI 0x5412
#define TARGET_TIOCGWINSZ 0x5413
#define TARGET_TIOCSWINSZ 0x5414
#define TARGET_TIOCMGET 0x5415
#define TARGET_TIOCMBIS 0x5416
#define TARGET_TIOCMBIC 0x5417
#define TARGET_TIOCMSET 0x5418
#define TARGET_TIOCGSOFTCAR 0x5419
#define TARGET_TIOCSSOFTCAR 0x541A
#define TARGET_FIONREAD 0x541B
#define TARGET_TIOCINQ FIONREAD
#define TARGET_TIOCLINUX 0x541C
#define TARGET_TIOCCONS 0x541D
#define TARGET_TIOCGSERIAL 0x541E
#define TARGET_TIOCSSERIAL 0x541F
#define TARGET_TIOCPKT 0x5420
#define TARGET_FIONBIO 0x5421
#define TARGET_TIOCNOTTY 0x5422
#define TARGET_TIOCSETD 0x5423
#define TARGET_TIOCGETD 0x5424
#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */
#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */
#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */
#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */
#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */
#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define TARGET_FIOCLEX 0x5451
#define TARGET_FIOASYNC 0x5452
#define TARGET_TIOCSERCONFIG 0x5453
#define TARGET_TIOCSERGWILD 0x5454
#define TARGET_TIOCSERSWILD 0x5455
#define TARGET_TIOCGLCKTRMIOS 0x5456
#define TARGET_TIOCSLCKTRMIOS 0x5457
#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
/* Used for packet mode */
#define TARGET_TIOCPKT_DATA 0
#define TARGET_TIOCPKT_FLUSHREAD 1
#define TARGET_TIOCPKT_FLUSHWRITE 2
#define TARGET_TIOCPKT_STOP 4
#define TARGET_TIOCPKT_START 8
#define TARGET_TIOCPKT_NOSTOP 16
#define TARGET_TIOCPKT_DOSTOP 32
#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */
/* from asm/termbits.h */
#define TARGET_NCCS 19
struct target_termios {
unsigned int c_iflag; /* input mode flags */
unsigned int c_oflag; /* output mode flags */
unsigned int c_cflag; /* control mode flags */
unsigned int c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[TARGET_NCCS]; /* control characters */
#define TARGET_NCC 8
struct target_termio {
unsigned short c_iflag; /* input mode flags */
unsigned short c_oflag; /* output mode flags */
unsigned short c_cflag; /* control mode flags */
unsigned short c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[TARGET_NCC]; /* control characters */
};
/* c_iflag bits */
#define TARGET_IGNBRK 0000001
#define TARGET_BRKINT 0000002
#define TARGET_IGNPAR 0000004
#define TARGET_PARMRK 0000010
#define TARGET_INPCK 0000020
#define TARGET_ISTRIP 0000040
#define TARGET_INLCR 0000100
#define TARGET_IGNCR 0000200
#define TARGET_ICRNL 0000400
#define TARGET_IUCLC 0001000
#define TARGET_IXON 0002000
#define TARGET_IXANY 0004000
#define TARGET_IXOFF 0010000
#define TARGET_IMAXBEL 0020000
struct target_winsize {
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel;
unsigned short ws_ypixel;
};
/* c_oflag bits */
#define TARGET_OPOST 0000001
#define TARGET_OLCUC 0000002
#define TARGET_ONLCR 0000004
#define TARGET_OCRNL 0000010
#define TARGET_ONOCR 0000020
#define TARGET_ONLRET 0000040
#define TARGET_OFILL 0000100
#define TARGET_OFDEL 0000200
#define TARGET_NLDLY 0000400
#define TARGET_NL0 0000000
#define TARGET_NL1 0000400
#define TARGET_CRDLY 0003000
#define TARGET_CR0 0000000
#define TARGET_CR1 0001000
#define TARGET_CR2 0002000
#define TARGET_CR3 0003000
#define TARGET_TABDLY 0014000
#define TARGET_TAB0 0000000
#define TARGET_TAB1 0004000
#define TARGET_TAB2 0010000
#define TARGET_TAB3 0014000
#define TARGET_XTABS 0014000
#define TARGET_BSDLY 0020000
#define TARGET_BS0 0000000
#define TARGET_BS1 0020000
#define TARGET_VTDLY 0040000
#define TARGET_VT0 0000000
#define TARGET_VT1 0040000
#define TARGET_FFDLY 0100000
#define TARGET_FF0 0000000
#define TARGET_FF1 0100000
/* c_cflag bit meaning */
#define TARGET_CBAUD 0010017
#define TARGET_B0 0000000 /* hang up */
#define TARGET_B50 0000001
#define TARGET_B75 0000002
#define TARGET_B110 0000003
#define TARGET_B134 0000004
#define TARGET_B150 0000005
#define TARGET_B200 0000006
#define TARGET_B300 0000007
#define TARGET_B600 0000010
#define TARGET_B1200 0000011
#define TARGET_B1800 0000012
#define TARGET_B2400 0000013
#define TARGET_B4800 0000014
#define TARGET_B9600 0000015
#define TARGET_B19200 0000016
#define TARGET_B38400 0000017
#define TARGET_EXTA B19200
#define TARGET_EXTB B38400
#define TARGET_CSIZE 0000060
#define TARGET_CS5 0000000
#define TARGET_CS6 0000020
#define TARGET_CS7 0000040
#define TARGET_CS8 0000060
#define TARGET_CSTOPB 0000100
#define TARGET_CREAD 0000200
#define TARGET_PARENB 0000400
#define TARGET_PARODD 0001000
#define TARGET_HUPCL 0002000
#define TARGET_CLOCAL 0004000
#define TARGET_CBAUDEX 0010000
#define TARGET_B57600 0010001
#define TARGET_B115200 0010002
#define TARGET_B230400 0010003
#define TARGET_B460800 0010004
#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */
#define TARGET_CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
#define TARGET_ISIG 0000001
#define TARGET_ICANON 0000002
#define TARGET_XCASE 0000004
#define TARGET_ECHO 0000010
#define TARGET_ECHOE 0000020
#define TARGET_ECHOK 0000040
#define TARGET_ECHONL 0000100
#define TARGET_NOFLSH 0000200
#define TARGET_TOSTOP 0000400
#define TARGET_ECHOCTL 0001000
#define TARGET_ECHOPRT 0002000
#define TARGET_ECHOKE 0004000
#define TARGET_FLUSHO 0010000
#define TARGET_PENDIN 0040000
#define TARGET_IEXTEN 0100000
/* c_cc character offsets */
#define TARGET_VINTR 0
#define TARGET_VQUIT 1
#define TARGET_VERASE 2
#define TARGET_VKILL 3
#define TARGET_VEOF 4
#define TARGET_VTIME 5
#define TARGET_VMIN 6
#define TARGET_VSWTC 7
#define TARGET_VSTART 8
#define TARGET_VSTOP 9
#define TARGET_VSUSP 10
#define TARGET_VEOL 11
#define TARGET_VREPRINT 12
#define TARGET_VDISCARD 13
#define TARGET_VWERASE 14
#define TARGET_VLNEXT 15
#define TARGET_VEOL2 16
#include "termbits.h"
#define TARGET_MAP_SHARED 0x01 /* Share changes */
#define TARGET_MAP_PRIVATE 0x02 /* Changes are private */
@@ -1163,6 +724,7 @@ struct target_termios {
#define TARGET_MAP_LOCKED 0x2000 /* pages are locked */
#define TARGET_MAP_NORESERVE 0x4000 /* don't check for reservations */
#if defined(TARGET_I386) || defined(TARGET_ARM)
struct target_stat {
unsigned short st_dev;
unsigned short __pad1;
@@ -1223,7 +785,111 @@ struct target_stat64 {
unsigned long long st_ino;
} __attribute__((packed));
#endif /* defined(TARGET_I386) || defined(TARGET_ARM) */
#elif defined(TARGET_SPARC)
struct target_stat {
unsigned short st_dev;
target_ulong st_ino;
unsigned short st_mode;
short st_nlink;
unsigned short st_uid;
unsigned short st_gid;
unsigned short st_rdev;
target_long st_size;
target_long target_st_atime;
target_ulong __unused1;
target_long target_st_mtime;
target_ulong __unused2;
target_long target_st_ctime;
target_ulong __unused3;
target_long st_blksize;
target_long st_blocks;
target_ulong __unused4[2];
};
struct target_stat64 {
unsigned char __pad0[6];
unsigned short st_dev;
uint64_t st_ino;
unsigned int st_mode;
unsigned int st_nlink;
unsigned int st_uid;
unsigned int st_gid;
unsigned char __pad2[6];
unsigned short st_rdev;
unsigned char __pad3[8];
int64_t st_size;
unsigned int st_blksize;
unsigned char __pad4[8];
unsigned int st_blocks;
unsigned int target_st_atime;
unsigned int __unused1;
unsigned int target_st_mtime;
unsigned int __unused2;
unsigned int target_st_ctime;
unsigned int __unused3;
unsigned int __unused4;
unsigned int __unused5;
};
#elif defined(TARGET_PPC)
struct target_stat {
unsigned short st_dev;
target_ulong st_ino;
unsigned int st_mode;
unsigned short st_nlink;
unsigned int st_uid;
unsigned int st_gid;
unsigned short st_rdev;
target_ulong st_size;
target_ulong st_blksize;
target_ulong st_blocks;
target_ulong target_st_atime;
target_ulong __unused1;
target_ulong target_st_mtime;
target_ulong __unused2;
target_ulong target_st_ctime;
target_ulong __unused3;
target_ulong __unused4;
target_ulong __unused5;
};
struct target_stat64 {
unsigned long long st_dev;
unsigned long long st_ino;
unsigned int st_mode;
unsigned int st_nlink;
unsigned int st_uid;
unsigned int st_gid;
unsigned long long st_rdev;
long long pad0;
long long st_size;
target_ulong st_blksize;
target_ulong pad1;
long long st_blocks; /* Number 512-byte blocks allocated. */
target_ulong target_st_atime;
target_ulong target_st_atime_nsec;
target_ulong target_st_mtime;
target_ulong target_st_mtime_nsec;
target_ulong target_st_ctime;
target_ulong target_st_ctime_nsec;
target_ulong __unused4;
target_ulong __unused5;
};
#endif /* defined(TARGET_PPC) */
#define TARGET_F_DUPFD 0 /* dup */
#define TARGET_F_GETFD 1 /* get close_on_exec */
@@ -1252,6 +918,62 @@ struct target_stat64 {
#define TARGET_F_SETLK64 13
#define TARGET_F_SETLKW64 14
#if defined (TARGET_ARM)
#define TARGET_O_ACCMODE 0003
#define TARGET_O_RDONLY 00
#define TARGET_O_WRONLY 01
#define TARGET_O_RDWR 02
#define TARGET_O_CREAT 0100 /* not fcntl */
#define TARGET_O_EXCL 0200 /* not fcntl */
#define TARGET_O_NOCTTY 0400 /* not fcntl */
#define TARGET_O_TRUNC 01000 /* not fcntl */
#define TARGET_O_APPEND 02000
#define TARGET_O_NONBLOCK 04000
#define TARGET_O_NDELAY O_NONBLOCK
#define TARGET_O_SYNC 010000
#define TARGET_FASYNC 020000 /* fcntl, for BSD compatibility */
#define TARGET_O_DIRECTORY 040000 /* must be a directory */
#define TARGET_O_NOFOLLOW 0100000 /* don't follow links */
#define TARGET_O_DIRECT 0200000 /* direct disk access hint */
#define TARGET_O_LARGEFILE 0400000
#elif defined (TARGET_PPC)
#define TARGET_O_ACCMODE 0003
#define TARGET_O_RDONLY 00
#define TARGET_O_WRONLY 01
#define TARGET_O_RDWR 02
#define TARGET_O_CREAT 0100 /* not fcntl */
#define TARGET_O_EXCL 0200 /* not fcntl */
#define TARGET_O_NOCTTY 0400 /* not fcntl */
#define TARGET_O_TRUNC 01000 /* not fcntl */
#define TARGET_O_APPEND 02000
#define TARGET_O_NONBLOCK 04000
#define TARGET_O_NDELAY O_NONBLOCK
#define TARGET_O_SYNC 010000
#define TARGET_FASYNC 020000 /* fcntl, for BSD compatibility */
#define TARGET_O_DIRECTORY 040000 /* must be a directory */
#define TARGET_O_NOFOLLOW 0100000 /* don't follow links */
#define TARGET_O_LARGEFILE 0200000
#define TARGET_O_DIRECT 0400000 /* direct disk access hint */
#else
#define TARGET_O_ACCMODE 0003
#define TARGET_O_RDONLY 00
#define TARGET_O_WRONLY 01
#define TARGET_O_RDWR 02
#define TARGET_O_CREAT 0100 /* not fcntl */
#define TARGET_O_EXCL 0200 /* not fcntl */
#define TARGET_O_NOCTTY 0400 /* not fcntl */
#define TARGET_O_TRUNC 01000 /* not fcntl */
#define TARGET_O_APPEND 02000
#define TARGET_O_NONBLOCK 04000
#define TARGET_O_NDELAY O_NONBLOCK
#define TARGET_O_SYNC 010000
#define TARGET_FASYNC 020000 /* fcntl, for BSD compatibility */
#define TARGET_O_DIRECT 040000 /* direct disk access hint */
#define TARGET_O_LARGEFILE 0100000
#define TARGET_O_DIRECTORY 0200000 /* must be a directory */
#define TARGET_O_NOFOLLOW 0400000 /* don't follow links */
#endif
struct target_flock {
short l_type;
short l_whence;
@@ -1411,3 +1133,20 @@ struct target_flock64 {
/* vfat ioctls */
#define TARGET_VFAT_IOCTL_READDIR_BOTH TARGET_IORU('r', 1)
#define TARGET_VFAT_IOCTL_READDIR_SHORT TARGET_IORU('r', 2)
struct target_sysinfo {
target_long uptime; /* Seconds since boot */
target_ulong loads[3]; /* 1, 5, and 15 minute load averages */
target_ulong totalram; /* Total usable main memory size */
target_ulong freeram; /* Available memory size */
target_ulong sharedram; /* Amount of shared memory */
target_ulong bufferram; /* Memory used by buffers */
target_ulong totalswap; /* Total swap space size */
target_ulong freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
unsigned short pad; /* explicit padding for m68k */
target_ulong totalhigh; /* Total high memory size */
target_ulong freehigh; /* Available high memory size */
unsigned int mem_unit; /* Memory unit size in bytes */
char _f[20-2*sizeof(target_long)-sizeof(int)]; /* Padding: libc5 uses this.. */
};

177
m68k.ld Normal file
View File

@@ -0,0 +1,177 @@
/* Script for -z combreloc: combine and sort reloc sections */
OUTPUT_FORMAT("elf32-m68k", "elf32-m68k",
"elf32-m68k")
OUTPUT_ARCH(m68k)
ENTRY(_start)
SEARCH_DIR("/usr/local/m68k-linux/lib");
/* Do we need any of these for elf?
__DYNAMIC = 0; */
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0x60000000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.dyn :
{
*(.rel.init)
*(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
*(.rel.fini)
*(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
*(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
*(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
*(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
*(.rel.ctors)
*(.rel.dtors)
*(.rel.got)
*(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
}
.rela.dyn :
{
*(.rela.init)
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
*(.rela.fini)
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
*(.rela.ctors)
*(.rela.dtors)
*(.rela.got)
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
}
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init :
{
KEEP (*(.init))
} =0x4e754e75
.plt : { *(.plt) }
.text :
{
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
} =0x4e754e75
.fini :
{
KEEP (*(.fini))
} =0x4e754e75
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.eh_frame_hdr : { *(.eh_frame_hdr) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN(0x2000) + (. & (0x2000 - 1));
/* Ensure the __preinit_array_start label is properly aligned. We
could instead move the label definition inside the section, but
the linker would then create the section even if it turns out to
be empty, which isn't pretty. */
. = ALIGN(32 / 8);
PROVIDE (__preinit_array_start = .);
.preinit_array : { *(.preinit_array) }
PROVIDE (__preinit_array_end = .);
PROVIDE (__init_array_start = .);
.init_array : { *(.init_array) }
PROVIDE (__init_array_end = .);
PROVIDE (__fini_array_start = .);
.fini_array : { *(.fini_array) }
PROVIDE (__fini_array_end = .);
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.eh_frame : { KEEP (*(.eh_frame)) }
.gcc_except_table : { *(.gcc_except_table) }
.dynamic : { *(.dynamic) }
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
/* We don't want to include the .ctor section from
from the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.got : { *(.got.plt) *(.got) }
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
. = ALIGN(32 / 8);
}
. = ALIGN(32 / 8);
_end = .;
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}

1787
monitor.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,244 +0,0 @@
void OPPROTO glue(glue(op_movs, SUFFIX), STRING_SUFFIX)(void)
{
int v, inc;
v = glue(ldu, SUFFIX)(SI_ADDR);
glue(st, SUFFIX)(DI_ADDR, v);
inc = (DF << SHIFT);
INC_SI();
INC_DI();
}
void OPPROTO glue(glue(op_rep_movs, SUFFIX), STRING_SUFFIX)(void)
{
int v, inc;
inc = (DF << SHIFT);
while (CX != 0) {
v = glue(ldu, SUFFIX)(SI_ADDR);
glue(st, SUFFIX)(DI_ADDR, v);
INC_SI();
INC_DI();
DEC_CX();
}
FORCE_RET();
}
void OPPROTO glue(glue(op_stos, SUFFIX), STRING_SUFFIX)(void)
{
int inc;
glue(st, SUFFIX)(DI_ADDR, EAX);
inc = (DF << SHIFT);
INC_DI();
}
void OPPROTO glue(glue(op_rep_stos, SUFFIX), STRING_SUFFIX)(void)
{
int inc;
inc = (DF << SHIFT);
while (CX != 0) {
glue(st, SUFFIX)(DI_ADDR, EAX);
INC_DI();
DEC_CX();
}
FORCE_RET();
}
void OPPROTO glue(glue(op_lods, SUFFIX), STRING_SUFFIX)(void)
{
int v, inc;
v = glue(ldu, SUFFIX)(SI_ADDR);
#if SHIFT == 0
EAX = (EAX & ~0xff) | v;
#elif SHIFT == 1
EAX = (EAX & ~0xffff) | v;
#else
EAX = v;
#endif
inc = (DF << SHIFT);
INC_SI();
}
/* don't know if it is used */
void OPPROTO glue(glue(op_rep_lods, SUFFIX), STRING_SUFFIX)(void)
{
int v, inc;
inc = (DF << SHIFT);
while (CX != 0) {
v = glue(ldu, SUFFIX)(SI_ADDR);
#if SHIFT == 0
EAX = (EAX & ~0xff) | v;
#elif SHIFT == 1
EAX = (EAX & ~0xffff) | v;
#else
EAX = v;
#endif
INC_SI();
DEC_CX();
}
FORCE_RET();
}
void OPPROTO glue(glue(op_scas, SUFFIX), STRING_SUFFIX)(void)
{
int v, inc;
v = glue(ldu, SUFFIX)(DI_ADDR);
inc = (DF << SHIFT);
INC_DI();
CC_SRC = v;
CC_DST = EAX - v;
}
void OPPROTO glue(glue(op_repz_scas, SUFFIX), STRING_SUFFIX)(void)
{
int v1, v2, inc;
if (CX != 0) {
/* NOTE: the flags are not modified if CX == 0 */
v1 = EAX & DATA_MASK;
inc = (DF << SHIFT);
do {
v2 = glue(ldu, SUFFIX)(DI_ADDR);
INC_DI();
DEC_CX();
if (v1 != v2)
break;
} while (CX != 0);
CC_SRC = v2;
CC_DST = v1 - v2;
CC_OP = CC_OP_SUBB + SHIFT;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_repnz_scas, SUFFIX), STRING_SUFFIX)(void)
{
int v1, v2, inc;
if (CX != 0) {
/* NOTE: the flags are not modified if CX == 0 */
v1 = EAX & DATA_MASK;
inc = (DF << SHIFT);
do {
v2 = glue(ldu, SUFFIX)(DI_ADDR);
INC_DI();
DEC_CX();
if (v1 == v2)
break;
} while (CX != 0);
CC_SRC = v2;
CC_DST = v1 - v2;
CC_OP = CC_OP_SUBB + SHIFT;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_cmps, SUFFIX), STRING_SUFFIX)(void)
{
int v1, v2, inc;
v1 = glue(ldu, SUFFIX)(SI_ADDR);
v2 = glue(ldu, SUFFIX)(DI_ADDR);
inc = (DF << SHIFT);
INC_SI();
INC_DI();
CC_SRC = v2;
CC_DST = v1 - v2;
}
void OPPROTO glue(glue(op_repz_cmps, SUFFIX), STRING_SUFFIX)(void)
{
int v1, v2, inc;
if (CX != 0) {
inc = (DF << SHIFT);
do {
v1 = glue(ldu, SUFFIX)(SI_ADDR);
v2 = glue(ldu, SUFFIX)(DI_ADDR);
INC_SI();
INC_DI();
DEC_CX();
if (v1 != v2)
break;
} while (CX != 0);
CC_SRC = v2;
CC_DST = v1 - v2;
CC_OP = CC_OP_SUBB + SHIFT;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_repnz_cmps, SUFFIX), STRING_SUFFIX)(void)
{
int v1, v2, inc;
if (CX != 0) {
inc = (DF << SHIFT);
do {
v1 = glue(ldu, SUFFIX)(SI_ADDR);
v2 = glue(ldu, SUFFIX)(DI_ADDR);
INC_SI();
INC_DI();
DEC_CX();
if (v1 == v2)
break;
} while (CX != 0);
CC_SRC = v2;
CC_DST = v1 - v2;
CC_OP = CC_OP_SUBB + SHIFT;
}
FORCE_RET();
}
void OPPROTO glue(glue(op_outs, SUFFIX), STRING_SUFFIX)(void)
{
int v, dx, inc;
dx = EDX & 0xffff;
v = glue(ldu, SUFFIX)(SI_ADDR);
glue(cpu_x86_out, SUFFIX)(env, dx, v);
inc = (DF << SHIFT);
INC_SI();
}
void OPPROTO glue(glue(op_rep_outs, SUFFIX), STRING_SUFFIX)(void)
{
int v, dx, inc;
inc = (DF << SHIFT);
dx = EDX & 0xffff;
while (CX != 0) {
v = glue(ldu, SUFFIX)(SI_ADDR);
glue(cpu_x86_out, SUFFIX)(env, dx, v);
INC_SI();
DEC_CX();
}
FORCE_RET();
}
void OPPROTO glue(glue(op_ins, SUFFIX), STRING_SUFFIX)(void)
{
int v, dx, inc;
dx = EDX & 0xffff;
v = glue(cpu_x86_in, SUFFIX)(env, dx);
glue(st, SUFFIX)(DI_ADDR, v);
inc = (DF << SHIFT);
INC_DI();
}
void OPPROTO glue(glue(op_rep_ins, SUFFIX), STRING_SUFFIX)(void)
{
int v, dx, inc;
inc = (DF << SHIFT);
dx = EDX & 0xffff;
while (CX != 0) {
v = glue(cpu_x86_in, SUFFIX)(env, dx);
glue(st, SUFFIX)(DI_ADDR, v);
INC_DI();
DEC_CX();
}
FORCE_RET();
}
#undef STRING_SUFFIX
#undef SI_ADDR
#undef DI_ADDR
#undef INC_SI
#undef INC_DI
#undef CX
#undef DEC_CX

473
osdep.c Normal file
View File

@@ -0,0 +1,473 @@
/*
* QEMU low level functions
*
* Copyright (c) 2003 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 <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "cpu.h"
#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(CONFIG_USER_ONLY)
#include <sys/mman.h>
#include <sys/ipc.h>
/* When not using soft mmu, libc independant functions are needed for
the CPU core because it needs to use alternates stacks and
libc/thread incompatibles settings */
#include <linux/unistd.h>
#define QEMU_SYSCALL0(name) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name)); \
return __res; \
}
#define QEMU_SYSCALL1(name,arg1) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1))); \
return __res; \
}
#define QEMU_SYSCALL2(name,arg1,arg2) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
return __res; \
}
#define QEMU_SYSCALL3(name,arg1,arg2,arg3) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3))); \
return __res; \
}
#define QEMU_SYSCALL4(name,arg1,arg2,arg3,arg4) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3)),"S" ((long)(arg4))); \
return __res; \
}
#define QEMU_SYSCALL5(name,arg1,arg2,arg3,arg4,arg5) \
{ \
long __res; \
__asm__ volatile ("int $0x80" \
: "=a" (__res) \
: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
return __res; \
}
#define QEMU_SYSCALL6(name,arg1,arg2,arg3,arg4,arg5,arg6) \
{ \
long __res; \
__asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; pop %%ebp" \
: "=a" (__res) \
: "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
"d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \
"0" ((long)(arg6))); \
return __res; \
}
int qemu_write(int fd, const void *buf, size_t n)
{
QEMU_SYSCALL3(write, fd, buf, n);
}
/****************************************************************/
/* shmat replacement */
int qemu_ipc(int call, unsigned long first,
unsigned long second, unsigned long third,
void *ptr, unsigned long fifth)
{
QEMU_SYSCALL6(ipc, call, first, second, third, ptr, fifth);
}
#define SHMAT 21
/* we must define shmat so that a specific address will be used when
mapping the X11 ximage */
void *shmat(int shmid, const void *shmaddr, int shmflg)
{
void *ptr;
int ret;
/* we give an address in the right memory area */
if (!shmaddr)
shmaddr = get_mmap_addr(8192 * 1024);
ret = qemu_ipc(SHMAT, shmid, shmflg, (unsigned long)&ptr, (void *)shmaddr, 0);
if (ret < 0)
return NULL;
return ptr;
}
/****************************************************************/
/* memory allocation */
//#define DEBUG_MALLOC
#define MALLOC_BASE 0xab000000
#define PHYS_RAM_BASE 0xac000000
#define MALLOC_ALIGN 16
#define BLOCK_HEADER_SIZE 16
typedef struct MemoryBlock {
struct MemoryBlock *next;
unsigned long size; /* size of block, including header */
} MemoryBlock;
static MemoryBlock *first_free_block;
static unsigned long malloc_addr = MALLOC_BASE;
static void *malloc_get_space(size_t size)
{
void *ptr;
size = TARGET_PAGE_ALIGN(size);
ptr = mmap((void *)malloc_addr, size,
PROT_WRITE | PROT_READ,
MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0);
if (ptr == MAP_FAILED)
return NULL;
malloc_addr += size;
return ptr;
}
void *qemu_malloc(size_t size)
{
MemoryBlock *mb, *mb1, **pmb;
void *ptr;
size_t size1, area_size;
if (size == 0)
return NULL;
size = (size + BLOCK_HEADER_SIZE + MALLOC_ALIGN - 1) & ~(MALLOC_ALIGN - 1);
pmb = &first_free_block;
for(;;) {
mb = *pmb;
if (mb == NULL)
break;
if (size <= mb->size)
goto found;
pmb = &mb->next;
}
/* no big enough blocks found: get new space */
area_size = TARGET_PAGE_ALIGN(size);
mb = malloc_get_space(area_size);
if (!mb)
return NULL;
size1 = area_size - size;
if (size1 > 0) {
/* create a new free block */
mb1 = (MemoryBlock *)((uint8_t *)mb + size);
mb1->next = NULL;
mb1->size = size1;
*pmb = mb1;
}
goto the_end;
found:
/* a free block was found: use it */
size1 = mb->size - size;
if (size1 > 0) {
/* create a new free block */
mb1 = (MemoryBlock *)((uint8_t *)mb + size);
mb1->next = mb->next;
mb1->size = size1;
*pmb = mb1;
} else {
/* suppress the first block */
*pmb = mb->next;
}
the_end:
mb->size = size;
mb->next = NULL;
ptr = ((uint8_t *)mb + BLOCK_HEADER_SIZE);
#ifdef DEBUG_MALLOC
qemu_printf("malloc: size=0x%x ptr=0x%lx\n", size, (unsigned long)ptr);
#endif
return ptr;
}
void qemu_free(void *ptr)
{
MemoryBlock *mb;
if (!ptr)
return;
mb = (MemoryBlock *)((uint8_t *)ptr - BLOCK_HEADER_SIZE);
mb->next = first_free_block;
first_free_block = mb;
}
/****************************************************************/
/* virtual memory allocation */
unsigned long mmap_addr = PHYS_RAM_BASE;
void *get_mmap_addr(unsigned long size)
{
unsigned long addr;
addr = mmap_addr;
mmap_addr += ((size + 4095) & ~4095) + 4096;
return (void *)addr;
}
#else
int qemu_write(int fd, const void *buf, size_t n)
{
int ret;
ret = write(fd, buf, n);
if (ret < 0)
return -errno;
else
return ret;
}
void *get_mmap_addr(unsigned long size)
{
return NULL;
}
void qemu_free(void *ptr)
{
free(ptr);
}
void *qemu_malloc(size_t size)
{
return malloc(size);
}
#endif
void *qemu_mallocz(size_t size)
{
void *ptr;
ptr = qemu_malloc(size);
if (!ptr)
return NULL;
memset(ptr, 0, size);
return ptr;
}
/****************************************************************/
/* printf support */
static inline int qemu_isdigit(int c)
{
return c >= '0' && c <= '9';
}
#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
/* from BSD ppp sources */
int qemu_vsnprintf(char *buf, int buflen, const char *fmt, va_list args)
{
int c, i, n;
int width, prec, fillch;
int base, len, neg;
unsigned long val = 0;
const char *f;
char *str, *buf0;
char num[32];
static const char hexchars[] = "0123456789abcdef";
buf0 = buf;
--buflen;
while (buflen > 0) {
for (f = fmt; *f != '%' && *f != 0; ++f)
;
if (f > fmt) {
len = f - fmt;
if (len > buflen)
len = buflen;
memcpy(buf, fmt, len);
buf += len;
buflen -= len;
fmt = f;
}
if (*fmt == 0)
break;
c = *++fmt;
width = prec = 0;
fillch = ' ';
if (c == '0') {
fillch = '0';
c = *++fmt;
}
if (c == '*') {
width = va_arg(args, int);
c = *++fmt;
} else {
while (qemu_isdigit(c)) {
width = width * 10 + c - '0';
c = *++fmt;
}
}
if (c == '.') {
c = *++fmt;
if (c == '*') {
prec = va_arg(args, int);
c = *++fmt;
} else {
while (qemu_isdigit(c)) {
prec = prec * 10 + c - '0';
c = *++fmt;
}
}
}
/* modifiers */
switch(c) {
case 'l':
c = *++fmt;
break;
default:
break;
}
str = 0;
base = 0;
neg = 0;
++fmt;
switch (c) {
case 'd':
i = va_arg(args, int);
if (i < 0) {
neg = 1;
val = -i;
} else
val = i;
base = 10;
break;
case 'o':
val = va_arg(args, unsigned int);
base = 8;
break;
case 'x':
case 'X':
val = va_arg(args, unsigned int);
base = 16;
break;
case 'p':
val = (unsigned long) va_arg(args, void *);
base = 16;
neg = 2;
break;
case 's':
str = va_arg(args, char *);
break;
case 'c':
num[0] = va_arg(args, int);
num[1] = 0;
str = num;
break;
default:
*buf++ = '%';
if (c != '%')
--fmt; /* so %z outputs %z etc. */
--buflen;
continue;
}
if (base != 0) {
str = num + sizeof(num);
*--str = 0;
while (str > num + neg) {
*--str = hexchars[val % base];
val = val / base;
if (--prec <= 0 && val == 0)
break;
}
switch (neg) {
case 1:
*--str = '-';
break;
case 2:
*--str = 'x';
*--str = '0';
break;
}
len = num + sizeof(num) - 1 - str;
} else {
len = strlen(str);
if (prec > 0 && len > prec)
len = prec;
}
if (width > 0) {
if (width > buflen)
width = buflen;
if ((n = width - len) > 0) {
buflen -= n;
for (; n > 0; --n)
*buf++ = fillch;
}
}
if (len > buflen)
len = buflen;
memcpy(buf, str, len);
buf += len;
buflen -= len;
}
*buf = 0;
return buf - buf0;
}
void qemu_vprintf(const char *fmt, va_list ap)
{
char buf[1024];
int len;
len = qemu_vsnprintf(buf, sizeof(buf), fmt, ap);
qemu_write(1, buf, len);
}
void qemu_printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
qemu_vprintf(fmt, ap);
va_end(ap);
}

26
osdep.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef QEMU_OSDEP_H
#define QEMU_OSDEP_H
#include <stdarg.h>
int qemu_vsnprintf(char *buf, int buflen, const char *fmt, va_list args);
void qemu_vprintf(const char *fmt, va_list ap);
void qemu_printf(const char *fmt, ...);
void *qemu_malloc(size_t size);
void *qemu_mallocz(size_t size);
void qemu_free(void *ptr);
void *get_mmap_addr(unsigned long size);
/* specific kludges for OS compatibility (should be moved elsewhere) */
#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(CONFIG_USER_ONLY)
/* disabled pthread version of longjmp which prevent us from using an
alternative signal stack */
extern void __longjmp(jmp_buf env, int val);
#define longjmp __longjmp
#endif
#endif

597
oss.c Normal file
View File

@@ -0,0 +1,597 @@
/*
* QEMU OSS Audio output driver
*
* Copyright (c) 2003 Vassili Karpov (malc)
*
* 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"
#if !defined(_WIN32) && !defined(__APPLE__)
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <inttypes.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
/* http://www.df.lth.se/~john_e/gems/gem002d.html */
/* http://www.multi-platforms.com/Tips/PopCount.htm */
static inline uint32_t popcount (uint32_t u)
{
u = ((u&0x55555555) + ((u>>1)&0x55555555));
u = ((u&0x33333333) + ((u>>2)&0x33333333));
u = ((u&0x0f0f0f0f) + ((u>>4)&0x0f0f0f0f));
u = ((u&0x00ff00ff) + ((u>>8)&0x00ff00ff));
u = ( u&0x0000ffff) + (u>>16);
return u;
}
static inline uint32_t lsbindex (uint32_t u)
{
return popcount ((u&-u)-1);
}
#define MIN(a, b) ((a)>(b)?(b):(a))
#define MAX(a, b) ((a)<(b)?(b):(a))
#define DEREF(x) (void)x
#define log(...) fprintf (stderr, "oss: " __VA_ARGS__)
#define ERRFail(...) do { \
int _errno = errno; \
fprintf (stderr, "oss: " __VA_ARGS__); \
fprintf (stderr, "system error: %s\n", strerror (_errno)); \
abort (); \
} while (0)
#define Fail(...) do { \
fprintf (stderr, "oss: " __VA_ARGS__); \
fprintf (stderr, "\n"); \
abort (); \
} while (0)
#ifdef DEBUG_OSS
#define lwarn(...) fprintf (stderr, "oss: " __VA_ARGS__)
#define linfo(...) fprintf (stderr, "oss: " __VA_ARGS__)
#define ldebug(...) fprintf (stderr, "oss: " __VA_ARGS__)
#else
#define lwarn(...)
#define linfo(...)
#define ldebug(...)
#endif
#define IOCTL(args) do { \
int ret = ioctl args; \
if (-1 == ret) { \
ERRFail (#args); \
} \
ldebug ("ioctl " #args " = %d\n", ret); \
} while (0)
static struct {
int fd;
int freq;
int bits16;
int nchannels;
int rpos;
int wpos;
int live;
int oss_fmt;
int bytes_per_second;
int is_mapped;
void *buf;
int bufsize;
int nfrags;
int fragsize;
int old_optr;
int leftover;
uint64_t old_ticks;
void (*copy_fn)(void *, void *, int);
} oss = { .fd = -1 };
static struct {
int try_mmap;
int nfrags;
int fragsize;
} conf = {
.try_mmap = 0,
.nfrags = 4,
.fragsize = 4096
};
static enum {DONT, DSP, TID} est = DONT;
static void copy_no_conversion (void *dst, void *src, int size)
{
memcpy (dst, src, size);
}
static void copy_u16_to_s16 (void *dst, void *src, int size)
{
int i;
uint16_t *out, *in;
out = dst;
in = src;
for (i = 0; i < size / 2; i++) {
out[i] = in[i] + 0x8000;
}
}
static void pab (struct audio_buf_info *abinfo)
{
DEREF (abinfo);
ldebug ("fragments %d, fragstotal %d, fragsize %d, bytes %d\n"
"rpos %d, wpos %d, live %d\n",
abinfo->fragments,
abinfo->fragstotal,
abinfo->fragsize,
abinfo->bytes,
rpos, wpos, live);
}
static void do_open ()
{
int mmmmssss;
audio_buf_info abinfo;
int fmt, freq, nchannels;
if (oss.buf) {
if (-1 == munmap (oss.buf, oss.bufsize)) {
ERRFail ("failed to unmap audio buffer %p %d",
oss.buf, oss.bufsize);
}
oss.buf = NULL;
}
if (-1 != oss.fd)
close (oss.fd);
oss.fd = open ("/dev/dsp", O_RDWR | O_NONBLOCK);
if (-1 == oss.fd) {
ERRFail ("can not open /dev/dsp");
}
fmt = oss.oss_fmt;
freq = oss.freq;
nchannels = oss.nchannels;
IOCTL ((oss.fd, SNDCTL_DSP_RESET, 1));
IOCTL ((oss.fd, SNDCTL_DSP_SAMPLESIZE, &fmt));
IOCTL ((oss.fd, SNDCTL_DSP_CHANNELS, &nchannels));
IOCTL ((oss.fd, SNDCTL_DSP_SPEED, &freq));
IOCTL ((oss.fd, SNDCTL_DSP_NONBLOCK));
mmmmssss = (conf.nfrags << 16) | conf.fragsize;
IOCTL ((oss.fd, SNDCTL_DSP_SETFRAGMENT, &mmmmssss));
if ((oss.oss_fmt != fmt)
|| (oss.nchannels != nchannels)
|| (oss.freq != freq)) {
Fail ("failed to set audio parameters\n"
"parameter | requested value | obtained value\n"
"format | %10d | %10d\n"
"channels | %10d | %10d\n"
"frequency | %10d | %10d\n",
oss.oss_fmt, fmt,
oss.nchannels, nchannels,
oss.freq, freq);
}
IOCTL ((oss.fd, SNDCTL_DSP_GETOSPACE, &abinfo));
oss.nfrags = abinfo.fragstotal;
oss.fragsize = abinfo.fragsize;
oss.bufsize = oss.nfrags * oss.fragsize;
oss.old_optr = 0;
oss.bytes_per_second = (freq << (nchannels >> 1)) << oss.bits16;
linfo ("bytes per second %d\n", oss.bytes_per_second);
linfo ("fragments %d, fragstotal %d, fragsize %d, bytes %d, bufsize %d\n",
abinfo.fragments,
abinfo.fragstotal,
abinfo.fragsize,
abinfo.bytes,
oss.bufsize);
oss.buf = MAP_FAILED;
oss.is_mapped = 0;
if (conf.try_mmap) {
oss.buf = mmap (NULL, oss.bufsize, PROT_WRITE, MAP_SHARED, oss.fd, 0);
if (MAP_FAILED == oss.buf) {
int err;
err = errno;
log ("failed to mmap audio, size %d, fd %d\n"
"syserr: %s\n",
oss.bufsize, oss.fd, strerror (err));
}
else {
est = TID;
oss.is_mapped = 1;
}
}
if (MAP_FAILED == oss.buf) {
est = TID;
oss.buf = mmap (NULL, oss.bufsize, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (MAP_FAILED == oss.buf) {
ERRFail ("mmap audio buf, size %d", oss.bufsize);
}
}
oss.rpos = 0;
oss.wpos = 0;
oss.live = 0;
if (oss.is_mapped) {
int trig;
trig = 0;
IOCTL ((oss.fd, SNDCTL_DSP_SETTRIGGER, &trig));
trig = PCM_ENABLE_OUTPUT;
IOCTL ((oss.fd, SNDCTL_DSP_SETTRIGGER, &trig));
}
}
static void maybe_open (int req_freq, int req_nchannels,
audfmt_e req_fmt, int force_open)
{
int oss_fmt, bits16;
switch (req_fmt) {
case AUD_FMT_U8:
bits16 = 0;
oss_fmt = AFMT_U8;
oss.copy_fn = copy_no_conversion;
break;
case AUD_FMT_S8:
Fail ("can not play 8bit signed");
case AUD_FMT_S16:
bits16 = 1;
oss_fmt = AFMT_S16_LE;
oss.copy_fn = copy_no_conversion;
break;
case AUD_FMT_U16:
bits16 = 1;
oss_fmt = AFMT_S16_LE;
oss.copy_fn = copy_u16_to_s16;
break;
default:
abort ();
}
if (force_open
|| (-1 == oss.fd)
|| (oss_fmt != oss.oss_fmt)
|| (req_nchannels != oss.nchannels)
|| (req_freq != oss.freq)
|| (bits16 != oss.bits16)) {
oss.oss_fmt = oss_fmt;
oss.nchannels = req_nchannels;
oss.freq = req_freq;
oss.bits16 = bits16;
do_open ();
}
}
void AUD_reset (int req_freq, int req_nchannels, audfmt_e req_fmt)
{
maybe_open (req_freq, req_nchannels, req_fmt, 0);
}
void AUD_open (int req_freq, int req_nchannels, audfmt_e req_fmt)
{
maybe_open (req_freq, req_nchannels, req_fmt, 1);
}
int AUD_write (void *in_buf, int size)
{
int to_copy, temp;
uint8_t *in, *out;
to_copy = MIN (oss.bufsize - oss.live, size);
temp = to_copy;
in = in_buf;
out = oss.buf;
while (temp) {
int copy;
copy = MIN (temp, oss.bufsize - oss.wpos);
oss.copy_fn (out + oss.wpos, in, copy);
oss.wpos += copy;
if (oss.wpos == oss.bufsize) {
oss.wpos = 0;
}
temp -= copy;
in += copy;
oss.live += copy;
}
return to_copy;
}
void AUD_run (void)
{
int res;
int bytes;
struct audio_buf_info abinfo;
if (0 == oss.live)
return;
if (oss.is_mapped) {
count_info info;
res = ioctl (oss.fd, SNDCTL_DSP_GETOPTR, &info);
if (-1 == res) {
int err;
err = errno;
lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err));
return;
}
if (info.ptr > oss.old_optr) {
bytes = info.ptr - oss.old_optr;
}
else {
bytes = oss.bufsize + info.ptr - oss.old_optr;
}
oss.old_optr = info.ptr;
oss.live -= bytes;
return;
}
res = ioctl (oss.fd, SNDCTL_DSP_GETOSPACE, &abinfo);
if (-1 == res) {
int err;
err = errno;
lwarn ("SNDCTL_DSP_GETOSPACE failed with %s\n", strerror (err));
}
bytes = abinfo.bytes;
bytes = MIN (oss.live, bytes);
#if 0
bytes = (bytes / fragsize) * fragsize;
#endif
while (bytes) {
int left, play, written;
left = oss.bufsize - oss.rpos;
play = MIN (left, bytes);
written = write (oss.fd, (void *) ((uint32_t) oss.buf + oss.rpos), play);
if (-1 == written) {
if (EAGAIN == errno || EINTR == errno) {
return;
}
else {
ERRFail ("write audio");
}
}
play = written;
oss.live -= play;
oss.rpos += play;
bytes -= play;
if (oss.rpos == oss.bufsize) {
oss.rpos = 0;
}
}
}
static int get_dsp_bytes (void)
{
int res;
struct count_info info;
res = ioctl (oss.fd, SNDCTL_DSP_GETOPTR, &info);
if (-1 == res) {
int err;
err = errno;
lwarn ("SNDCTL_DSP_GETOPTR failed with %s\n", strerror (err));
return -1;
}
else {
ldebug ("bytes %d\n", info.bytes);
return info.bytes;
}
}
void AUD_adjust_estimate (int leftover)
{
oss.leftover = leftover;
}
int AUD_get_free (void)
{
int free, elapsed;
free = oss.bufsize - oss.live;
if (0 == free)
return 0;
elapsed = free;
switch (est) {
case DONT:
break;
case DSP:
{
static int old_bytes;
int bytes;
bytes = get_dsp_bytes ();
if (bytes <= 0)
return free;
elapsed = bytes - old_bytes;
old_bytes = bytes;
ldebug ("dsp elapsed %d bytes\n", elapsed);
break;
}
case TID:
{
uint64_t ticks, delta;
uint64_t ua_elapsed;
uint64_t al_elapsed;
ticks = qemu_get_clock(rt_clock);
delta = ticks - oss.old_ticks;
oss.old_ticks = ticks;
ua_elapsed = (delta * oss.bytes_per_second) / 1000;
al_elapsed = ua_elapsed & ~3ULL;
ldebug ("tid elapsed %llu bytes\n", ua_elapsed);
if (al_elapsed > (uint64_t) INT_MAX)
elapsed = INT_MAX;
else
elapsed = al_elapsed;
elapsed += oss.leftover;
}
}
if (elapsed > free) {
lwarn ("audio can not keep up elapsed %d free %d\n", elapsed, free);
return free;
}
else {
return elapsed;
}
}
int AUD_get_live (void)
{
return oss.live;
}
int AUD_get_buffer_size (void)
{
return oss.bufsize;
}
#define QC_OSS_FRAGSIZE "QEMU_OSS_FRAGSIZE"
#define QC_OSS_NFRAGS "QEMU_OSS_NFRAGS"
#define QC_OSS_MMAP "QEMU_OSS_MMAP"
static int get_conf_val (const char *key, int defval)
{
int val = defval;
char *strval;
strval = getenv (key);
if (strval) {
val = atoi (strval);
}
return val;
}
void AUD_init (void)
{
int fsp;
DEREF (pab);
conf.fragsize = get_conf_val (QC_OSS_FRAGSIZE, conf.fragsize);
conf.nfrags = get_conf_val (QC_OSS_NFRAGS, conf.nfrags);
conf.try_mmap = get_conf_val (QC_OSS_MMAP, conf.try_mmap);
fsp = conf.fragsize;
if (0 != (fsp & (fsp - 1))) {
Fail ("fragment size %d is not power of 2", fsp);
}
conf.fragsize = lsbindex (fsp);
}
#else
void AUD_run (void)
{
}
int AUD_write (void *in_buf, int size)
{
return 0;
}
void AUD_reset (int rfreq, int rnchannels, audfmt_e rfmt)
{
}
void AUD_adjust_estimate (int _leftover)
{
}
int AUD_get_free (void)
{
return 0;
}
int AUD_get_live (void)
{
return 0;
}
int AUD_get_buffer_size (void)
{
return 0;
}
void AUD_init (void)
{
}
#endif

24
pc-bios/Makefile Normal file
View File

@@ -0,0 +1,24 @@
#
# NOTE: only compilable with x86 cross compile tools
#
include ../config-host.mak
DEFINES=
TARGETS=
ifeq ($(ARCH),i386)
TARGETS+=linux_boot.bin
endif
all: $(TARGETS)
linux_boot.bin: linux_boot.o
ld --oformat binary -Ttext 0 -o $@ $<
chmod a-x $@
%.o: %.S
$(CC) $(DEFINES) -c -o $@ $<
clean:
rm -f $(TARGETS) *.o *~

8
pc-bios/README Normal file
View File

@@ -0,0 +1,8 @@
- The PC BIOS comes from the Bochs project
(http://bochs.sourceforge.net/). A patch from bios.diff was applied.
- The VGA BIOS and the Cirrus VGA BIOS come from the LGPL VGA bios
project (http://www.nongnu.org/vgabios/).
- The PowerPC Open Hack'Ware Open Firmware Compatible BIOS is
available at http://site.voila.fr/jmayer/OpenHackWare/index.htm.

BIN
pc-bios/bios.bin Normal file

Binary file not shown.

104
pc-bios/bios.diff Normal file
View File

@@ -0,0 +1,104 @@
Index: rombios.c
===================================================================
RCS file: /cvsroot/bochs/bochs/bios/rombios.c,v
retrieving revision 1.110
diff -u -w -r1.110 rombios.c
--- rombios.c 31 May 2004 13:11:27 -0000 1.110
+++ rombios.c 20 Jun 2004 13:10:07 -0000
@@ -137,6 +137,7 @@
#define DEBUG_INT16 0
#define DEBUG_INT1A 0
#define DEBUG_INT74 0
+#define DEBUG_APM 0
#define BX_CPU 3
#define BX_USE_PS2_MOUSE 1
@@ -145,6 +146,7 @@
#define BX_SUPPORT_FLOPPY 1
#define BX_FLOPPY_ON_CNT 37 // 2 seconds
#define BX_PCIBIOS 1
+#define BX_APM 1
#define BX_USE_ATADRV 1
#define BX_ELTORITO_BOOT 1
@@ -230,17 +232,6 @@
out dx,ax
MEND
-MACRO HALT2
- ;; the HALT macro is called with the line number of the HALT call.
- ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex
- ;; to print a BX_PANIC message. This will normally halt the simulation
- ;; with a message such as "BIOS panic at rombios.c, line 4091".
- ;; However, users can choose to make panics non-fatal and continue.
- mov dx,#PANIC_PORT2
- mov ax,#?1
- out dx,ax
-MEND
-
MACRO JMP_AP
db 0xea
dw ?2
@@ -1543,15 +1534,12 @@
}
if (action & BIOS_PRINTF_HALT) {
- // freeze in a busy loop. If I do a HLT instruction, then in versions
- // 1.3.pre1 and earlier, it will panic without ever updating the VGA
- // display, so the panic message will not be visible. By waiting
- // forever, you are certain to see the panic message on screen.
- // After a few more versions have passed, we can turn this back into
- // a halt or something.
- // do {} while (1);
+ // freeze in a busy loop.
ASM_START
- HALT2(__LINE__)
+ cli
+ halt2_loop:
+ hlt
+ jmp halt2_loop
ASM_END
}
}
@@ -8344,6 +8332,19 @@
pop ax
iret
+
+;--------------------
+#if BX_APM
+use32 386
+#define APM_PROT32
+#include "apmbios.S"
+use16 386
+
+#define APM_REAL
+#include "apmbios.S"
+
+#endif
+
;--------------------
#if BX_PCIBIOS
use32 386
@@ -9560,6 +9561,10 @@
.org 0xf859 ; INT 15h System Services Entry Point
int15_handler:
pushf
+#if BX_APM
+ cmp ah, #0x53
+ je apm_call
+#endif
push ds
push es
pushad
@@ -9570,6 +9575,10 @@
popf
//JMPL(iret_modify_cf)
jmp iret_modify_cf
+#if BX_APM
+apm_call:
+ jmp _apmreal_entry
+#endif
;; Protected mode IDT descriptor
;;

29
pc-bios/linux_boot.S Normal file
View File

@@ -0,0 +1,29 @@
/*
* QEMU Boot sector to launch a preloaded Linux kernel
* Copyright (c) 2004 Fabrice Bellard
*/
#define LOAD_SEG 0x9000
.code16
.text
.globl _start
_start:
cli
cld
mov $LOAD_SEG, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
mov $0x8ffe, %sp
ljmp $LOAD_SEG + 0x20, $0
1:
.fill 510 - (1b - _start), 1, 0
/* boot sector signature */
.byte 0x55
.byte 0xaa

BIN
pc-bios/linux_boot.bin Normal file

Binary file not shown.

BIN
pc-bios/ppc_rom.bin Normal file

Binary file not shown.

BIN
pc-bios/vgabios-cirrus.bin Normal file

Binary file not shown.

BIN
pc-bios/vgabios.bin Normal file

Binary file not shown.

245
ppc-dis.c
View File

@@ -48,18 +48,18 @@ struct powerpc_opcode
/* The opcode itself. Those bits which will be filled in with
operands are zeroes. */
unsigned long opcode;
uint32_t opcode;
/* The opcode mask. This is used by the disassembler. This is a
mask containing ones indicating those bits which must match the
opcode field, and zeroes indicating those bits which need not
match (and are presumably filled in by operands). */
unsigned long mask;
uint32_t mask;
/* One bit flags for the opcode. These are used to indicate which
specific processors support the instructions. The defined values
are listed below. */
unsigned long flags;
uint32_t flags;
/* An array of operand codes. Each code is an index into the
operand table. They appear in the order which the operands must
@@ -124,7 +124,7 @@ struct powerpc_operand
string (the operand will be inserted in any case). If the
operand value is legal, *ERRMSG will be unchanged (most operands
can accept any value). */
unsigned long (*insert)(unsigned long instruction, long op,
unsigned long (*insert)(uint32_t instruction, int32_t op,
const char **errmsg);
/* Extraction function. This is used by the disassembler. To
@@ -144,10 +144,10 @@ struct powerpc_operand
non-zero if this operand type can not actually be extracted from
this operand (i.e., the instruction does not match). If the
operand is valid, *INVALID will not be changed. */
long (*extract) (unsigned long instruction, int *invalid);
long (*extract) (uint32_t instruction, int *invalid);
/* One bit syntax flags. */
unsigned long flags;
uint32_t flags;
};
/* Elements in the table are retrieved by indexing with values from
@@ -244,7 +244,7 @@ struct powerpc_macro
/* One bit flags for the opcode. These are used to indicate which
specific processors support the instructions. The values are the
same as those for the struct powerpc_opcode flags field. */
unsigned long flags;
uint32_t flags;
/* A format string to turn the macro into a normal instruction.
Each %N in the string is replaced with operand number N (zero
@@ -288,43 +288,43 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
/* Local insertion and extraction functions. */
static unsigned long insert_bat (unsigned long, long, const char **);
static long extract_bat(unsigned long, int *);
static unsigned long insert_bba(unsigned long, long, const char **);
static long extract_bba(unsigned long, int *);
static unsigned long insert_bd(unsigned long, long, const char **);
static long extract_bd(unsigned long, int *);
static unsigned long insert_bdm(unsigned long, long, const char **);
static long extract_bdm(unsigned long, int *);
static unsigned long insert_bdp(unsigned long, long, const char **);
static long extract_bdp(unsigned long, int *);
static unsigned long insert_bo(unsigned long, long, const char **);
static long extract_bo(unsigned long, int *);
static unsigned long insert_boe(unsigned long, long, const char **);
static long extract_boe(unsigned long, int *);
static unsigned long insert_ds(unsigned long, long, const char **);
static long extract_ds(unsigned long, int *);
static unsigned long insert_li(unsigned long, long, const char **);
static long extract_li(unsigned long, int *);
static unsigned long insert_mbe(unsigned long, long, const char **);
static long extract_mbe(unsigned long, int *);
static unsigned long insert_mb6(unsigned long, long, const char **);
static long extract_mb6(unsigned long, int *);
static unsigned long insert_nb(unsigned long, long, const char **);
static long extract_nb(unsigned long, int *);
static unsigned long insert_nsi(unsigned long, long, const char **);
static long extract_nsi(unsigned long, int *);
static unsigned long insert_ral(unsigned long, long, const char **);
static unsigned long insert_ram(unsigned long, long, const char **);
static unsigned long insert_ras(unsigned long, long, const char **);
static unsigned long insert_rbs(unsigned long, long, const char **);
static long extract_rbs(unsigned long, int *);
static unsigned long insert_sh6(unsigned long, long, const char **);
static long extract_sh6(unsigned long, int *);
static unsigned long insert_spr(unsigned long, long, const char **);
static long extract_spr(unsigned long, int *);
static unsigned long insert_tbr(unsigned long, long, const char **);
static long extract_tbr(unsigned long, int *);
static unsigned long insert_bat (uint32_t, int32_t, const char **);
static long extract_bat(uint32_t, int *);
static unsigned long insert_bba(uint32_t, int32_t, const char **);
static long extract_bba(uint32_t, int *);
static unsigned long insert_bd(uint32_t, int32_t, const char **);
static long extract_bd(uint32_t, int *);
static unsigned long insert_bdm(uint32_t, int32_t, const char **);
static long extract_bdm(uint32_t, int *);
static unsigned long insert_bdp(uint32_t, int32_t, const char **);
static long extract_bdp(uint32_t, int *);
static unsigned long insert_bo(uint32_t, int32_t, const char **);
static long extract_bo(uint32_t, int *);
static unsigned long insert_boe(uint32_t, int32_t, const char **);
static long extract_boe(uint32_t, int *);
static unsigned long insert_ds(uint32_t, int32_t, const char **);
static long extract_ds(uint32_t, int *);
static unsigned long insert_li(uint32_t, int32_t, const char **);
static long extract_li(uint32_t, int *);
static unsigned long insert_mbe(uint32_t, int32_t, const char **);
static long extract_mbe(uint32_t, int *);
static unsigned long insert_mb6(uint32_t, int32_t, const char **);
static long extract_mb6(uint32_t, int *);
static unsigned long insert_nb(uint32_t, int32_t, const char **);
static long extract_nb(uint32_t, int *);
static unsigned long insert_nsi(uint32_t, int32_t, const char **);
static long extract_nsi(uint32_t, int *);
static unsigned long insert_ral(uint32_t, int32_t, const char **);
static unsigned long insert_ram(uint32_t, int32_t, const char **);
static unsigned long insert_ras(uint32_t, int32_t, const char **);
static unsigned long insert_rbs(uint32_t, int32_t, const char **);
static long extract_rbs(uint32_t, int *);
static unsigned long insert_sh6(uint32_t, int32_t, const char **);
static long extract_sh6(uint32_t, int *);
static unsigned long insert_spr(uint32_t, int32_t, const char **);
static long extract_spr(uint32_t, int *);
static unsigned long insert_tbr(uint32_t, int32_t, const char **);
static long extract_tbr(uint32_t, int *);
/* The operands table.
@@ -648,8 +648,8 @@ const struct powerpc_operand powerpc_operands[] =
/*ARGSUSED*/
static unsigned long
insert_bat (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
return insn | (((insn >> 21) & 0x1f) << 16);
@@ -657,7 +657,7 @@ insert_bat (insn, value, errmsg)
static long
extract_bat (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
if (invalid != (int *) NULL
@@ -675,8 +675,8 @@ extract_bat (insn, invalid)
/*ARGSUSED*/
static unsigned long
insert_bba (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
return insn | (((insn >> 16) & 0x1f) << 11);
@@ -684,7 +684,7 @@ insert_bba (insn, value, errmsg)
static long
extract_bba (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
if (invalid != (int *) NULL
@@ -699,8 +699,8 @@ extract_bba (insn, invalid)
/*ARGSUSED*/
static unsigned long
insert_bd (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
return insn | (value & 0xfffc);
@@ -709,7 +709,7 @@ insert_bd (insn, value, errmsg)
/*ARGSUSED*/
static long
extract_bd (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
if ((insn & 0x8000) != 0)
@@ -728,8 +728,8 @@ extract_bd (insn, invalid)
/*ARGSUSED*/
static unsigned long
insert_bdm (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
if ((value & 0x8000) != 0)
@@ -739,7 +739,7 @@ insert_bdm (insn, value, errmsg)
static long
extract_bdm (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
if (invalid != (int *) NULL
@@ -759,8 +759,8 @@ extract_bdm (insn, invalid)
/*ARGSUSED*/
static unsigned long
insert_bdp (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
if ((value & 0x8000) == 0)
@@ -770,7 +770,7 @@ insert_bdp (insn, value, errmsg)
static long
extract_bdp (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
if (invalid != (int *) NULL
@@ -786,7 +786,7 @@ extract_bdp (insn, invalid)
/* Check for legal values of a BO field. */
static int
valid_bo (long value)
valid_bo (int32_t value)
{
/* Certain encodings have bits that are required to be zero. These
are (z must be zero, y may be anything):
@@ -815,8 +815,8 @@ valid_bo (long value)
static unsigned long
insert_bo (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
if (errmsg != (const char **) NULL
@@ -827,10 +827,10 @@ insert_bo (insn, value, errmsg)
static long
extract_bo (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
long value;
int32_t value;
value = (insn >> 21) & 0x1f;
if (invalid != (int *) NULL
@@ -845,8 +845,8 @@ extract_bo (insn, invalid)
static unsigned long
insert_boe (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
if (errmsg != (const char **) NULL)
@@ -861,10 +861,10 @@ insert_boe (insn, value, errmsg)
static long
extract_boe (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
long value;
int32_t value;
value = (insn >> 21) & 0x1f;
if (invalid != (int *) NULL
@@ -879,8 +879,8 @@ extract_boe (insn, invalid)
/*ARGSUSED*/
static unsigned long
insert_ds (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
return insn | (value & 0xfffc);
@@ -889,7 +889,7 @@ insert_ds (insn, value, errmsg)
/*ARGSUSED*/
static long
extract_ds (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
if ((insn & 0x8000) != 0)
@@ -904,8 +904,8 @@ extract_ds (insn, invalid)
/*ARGSUSED*/
static unsigned long
insert_li (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
return insn | (value & 0x3fffffc);
@@ -914,7 +914,7 @@ insert_li (insn, value, errmsg)
/*ARGSUSED*/
static long
extract_li (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
if ((insn & 0x2000000) != 0)
@@ -930,11 +930,11 @@ extract_li (insn, invalid)
static unsigned long
insert_mbe (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
unsigned long uval;
uint32_t uval;
int mb, me;
uval = value;
@@ -972,7 +972,7 @@ insert_mbe (insn, value, errmsg)
static long
extract_mbe (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
long ret;
@@ -996,8 +996,8 @@ extract_mbe (insn, invalid)
/*ARGSUSED*/
static unsigned long
insert_mb6 (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
return insn | ((value & 0x1f) << 6) | (value & 0x20);
@@ -1006,7 +1006,7 @@ insert_mb6 (insn, value, errmsg)
/*ARGSUSED*/
static long
extract_mb6 (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
return ((insn >> 6) & 0x1f) | (insn & 0x20);
@@ -1017,8 +1017,8 @@ extract_mb6 (insn, invalid)
static unsigned long
insert_nb (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
if (value < 0 || value > 32)
@@ -1031,7 +1031,7 @@ insert_nb (insn, value, errmsg)
/*ARGSUSED*/
static long
extract_nb (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
long ret;
@@ -1050,8 +1050,8 @@ extract_nb (insn, invalid)
/*ARGSUSED*/
static unsigned long
insert_nsi (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
return insn | ((- value) & 0xffff);
@@ -1059,7 +1059,7 @@ insert_nsi (insn, value, errmsg)
static long
extract_nsi (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
if (invalid != (int *) NULL)
@@ -1076,8 +1076,8 @@ extract_nsi (insn, invalid)
static unsigned long
insert_ral (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
if (value == 0
@@ -1091,8 +1091,8 @@ insert_ral (insn, value, errmsg)
static unsigned long
insert_ram (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
if (value >= ((insn >> 21) & 0x1f))
@@ -1106,8 +1106,8 @@ insert_ram (insn, value, errmsg)
static unsigned long
insert_ras (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
if (value == 0)
@@ -1124,8 +1124,8 @@ insert_ras (insn, value, errmsg)
/*ARGSUSED*/
static unsigned long
insert_rbs (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
return insn | (((insn >> 21) & 0x1f) << 11);
@@ -1133,7 +1133,7 @@ insert_rbs (insn, value, errmsg)
static long
extract_rbs (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
if (invalid != (int *) NULL
@@ -1147,8 +1147,8 @@ extract_rbs (insn, invalid)
/*ARGSUSED*/
static unsigned long
insert_sh6 (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4);
@@ -1157,7 +1157,7 @@ insert_sh6 (insn, value, errmsg)
/*ARGSUSED*/
static long
extract_sh6 (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
return ((insn >> 11) & 0x1f) | ((insn << 4) & 0x20);
@@ -1168,8 +1168,8 @@ extract_sh6 (insn, invalid)
static unsigned long
insert_spr (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
@@ -1177,7 +1177,7 @@ insert_spr (insn, value, errmsg)
static long
extract_spr (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0);
@@ -1195,8 +1195,8 @@ extract_spr (insn, invalid)
static unsigned long
insert_tbr (insn, value, errmsg)
unsigned long insn;
long value;
uint32_t insn;
int32_t value;
const char **errmsg;
{
if (value == 0)
@@ -1206,7 +1206,7 @@ insert_tbr (insn, value, errmsg)
static long
extract_tbr (insn, invalid)
unsigned long insn;
uint32_t insn;
int *invalid;
{
long ret;
@@ -3067,27 +3067,30 @@ const struct powerpc_macro powerpc_macros[] = {
const int powerpc_num_macros =
sizeof (powerpc_macros) / sizeof (powerpc_macros[0]);
static int print_insn_powerpc(FILE *, unsigned long insn, unsigned memaddr, int dialect);
static int print_insn_powerpc(FILE *, uint32_t insn, unsigned memaddr, int dialect);
/* Print a big endian PowerPC instruction. For convenience, also
disassemble instructions supported by the Motorola PowerPC 601. */
#include "cpu.h"
int print_insn_ppc (bfd_vma pc, disassemble_info *info)
{
return print_insn_powerpc (info->stream,
(unsigned int)bfd_getb32((bfd_byte *)pc), pc,
PPC_OPCODE_PPC | PPC_OPCODE_601);
uint32_t opc;
(*info->read_memory_func)(pc, (bfd_byte *)(&opc), 4, info);
return print_insn_powerpc (info->stream, tswap32(opc), pc,
PPC | B32 | M601);
}
/* Print a PowerPC or POWER instruction. */
static int
print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
int
print_insn_powerpc (FILE *out, uint32_t insn, unsigned memaddr,
int dialect)
{
const struct powerpc_opcode *opcode;
const struct powerpc_opcode *opcode_end;
unsigned long op;
uint32_t op;
/* Get the major opcode of the instruction. */
op = PPC_OP (insn);
@@ -3097,7 +3100,7 @@ print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
opcode_end = powerpc_opcodes + powerpc_num_opcodes;
for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++)
{
unsigned long table_op;
uint32_t table_op;
const unsigned char *opindex;
const struct powerpc_operand *operand;
int invalid;
@@ -3137,7 +3140,7 @@ print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
need_paren = 0;
for (opindex = opcode->operands; *opindex != 0; opindex++)
{
long value;
int32_t value;
operand = powerpc_operands + *opindex;
@@ -3173,20 +3176,20 @@ print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
/* Print the operand as directed by the flags. */
if ((operand->flags & PPC_OPERAND_GPR) != 0)
fprintf(out, "r%ld", value);
fprintf(out, "r%d", value);
else if ((operand->flags & PPC_OPERAND_FPR) != 0)
fprintf(out, "f%ld", value);
fprintf(out, "f%d", value);
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
fprintf(out, "%08lX", memaddr + value);
fprintf(out, "%08X", memaddr + value);
else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
fprintf(out, "%08lX", value & 0xffffffff);
fprintf(out, "%08X", value & 0xffffffff);
else if ((operand->flags & PPC_OPERAND_CR) == 0
|| (dialect & PPC_OPCODE_PPC) == 0)
fprintf(out, "%ld", value);
fprintf(out, "%d", value);
else
{
if (operand->bits == 3)
fprintf(out, "cr%ld", value);
fprintf(out, "cr%d", value);
else
{
static const char *cbnames[4] = { "lt", "gt", "eq", "so" };
@@ -3226,7 +3229,7 @@ print_insn_powerpc (FILE *out, unsigned long insn, unsigned memaddr,
}
/* We could not find a match. */
fprintf(out, ".long 0x%lx", insn);
fprintf(out, ".long 0x%x", insn);
return 4;
}

34
qemu-binfmt-conf.sh Normal file
View File

@@ -0,0 +1,34 @@
#!/bin/sh
# enable automatic i386/ARM/SPARC/PPC program execution by the kernel
# load the binfmt_misc module
/sbin/modprobe binfmt_misc
# probe cpu type
cpu=`uname -m`
case "$cpu" in
i386|i486|i586|i686|i86pc|BePC)
cpu="i386"
;;
"Power Macintosh"|ppc|ppc64)
cpu="ppc"
;;
armv4l)
cpu="arm"
;;
esac
# register the interpreter for each cpu except for the native one
if [ $cpu != "i386" ] ; then
echo ':i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register
echo ':i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register
fi
if [ $cpu != "arm" ] ; then
echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-arm:' > /proc/sys/fs/binfmt_misc/register
fi
if [ $cpu != "sparc" ] ; then
echo ':sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-sparc:' > /proc/sys/fs/binfmt_misc/register
fi
if [ $cpu != "ppc" ] ; then
echo ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-ppc:' > /proc/sys/fs/binfmt_misc/register
fi

File diff suppressed because it is too large Load Diff

105
qemu-mkcow.1 Normal file
View File

@@ -0,0 +1,105 @@
.\" $Header: /home/paul/qemu/svnmerge/qemu-cvs/qemu/qemu-mkcow.1,v 1.1 2004-03-26 22:42:54 bellard Exp $
.\"
.\" transcript compatibility for postscript use.
.\"
.\" synopsis: .P! <file.ps>
.\"
.de P!
.fl
\!!1 setgray
.fl
\\&.\"
.fl
\!!0 setgray
.fl \" force out current output buffer
\!!save /psv exch def currentpoint translate 0 0 moveto
\!!/showpage{}def
.fl \" prolog
.sy sed -e 's/^/!/' \\$1\" bring in postscript file
\!!psv restore
.
.de pF
.ie \\*(f1 .ds f1 \\n(.f
.el .ie \\*(f2 .ds f2 \\n(.f
.el .ie \\*(f3 .ds f3 \\n(.f
.el .ie \\*(f4 .ds f4 \\n(.f
.el .tm ? font overflow
.ft \\$1
..
.de fP
.ie !\\*(f4 \{\
. ft \\*(f4
. ds f4\"
' br \}
.el .ie !\\*(f3 \{\
. ft \\*(f3
. ds f3\"
' br \}
.el .ie !\\*(f2 \{\
. ft \\*(f2
. ds f2\"
' br \}
.el .ie !\\*(f1 \{\
. ft \\*(f1
. ds f1\"
' br \}
.el .tm ? font underflow
..
.ds f1\"
.ds f2\"
.ds f3\"
.ds f4\"
'\" t
.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n
.TH "QEMU" "8"
.SH "NAME"
qemu-mkcow \(em create a copy-on-write file for qemu
.SH "SYNOPSIS"
.PP
\fBqemu-mkcow\fR [\fB-h\fP] [\fB-f \fImaster_disk_image\fR\fP] [\fIcow_image\fR] [\fB\fIcow_size\fR\fP]
.SH "DESCRIPTION"
.PP
The \fBqemu-mkcow\fR command creates a
persistent copy-on-write file for \fBqemu\fR.
.PP
\fBqemu\fR can be used in a "copy-on-write" mode,
where changes made by \fBqemu\fR do not actually
change the disk image file. One way is to invoke
\fBqemu\fR with -snapshot: these changes
are stored in a temporary file, which is discarded when
\fBqemu\fR exits.
.PP
\fBqemu-mkcow\fR creates an explicit copy-on-write
file where changes are to be stored: this way, changes made
inside \fBqemu\fR will still be there next time you
run it, although the master disk image isn't ever changed.
.PP
The usual method is to create the master image, then create a
copy-on-write file using \fBqemu-mkcow\fR with
\fB-f\fP. The filename of the master image is stored
inside the generated copy-on-write file: it must not be modified
after this is run!
.PP
If no master file is specified, the effect is that of a
blank master of size \fIcow_size\fR.
.SH "SEE ALSO"
.PP
qemu(1), qemu-fast(1).
.SH "AUTHOR"
.PP
This manual page was written by Paul Russell prussell@debian.org for
the \fBDebian\fP system (but may be used by others). Permission is
granted to copy, distribute and/or modify this document under
the terms of the GNU General Public License, Version 2 any
later version published by the Free Software Foundation.
.PP
On Debian systems, the complete text of the GNU General Public
License can be found in /usr/share/common-licenses/GPL.
.\" created by instant / docbook-to-man, Fri 12 Mar 2004, 05:58

View File

@@ -28,22 +28,17 @@
#include <getopt.h>
#include <inttypes.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <malloc.h>
#include <termios.h>
#include <sys/poll.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include "vl.h"
#include "cow.h"
#define NO_THUNK_TYPE_SIZE
#include "thunk.h"
#include "bswap.h"
int cow_create(int cow_fd, const char *image_filename,
int64_t image_sectors)
@@ -85,8 +80,8 @@ int cow_create(int cow_fd, const char *image_filename,
void help(void)
{
printf("vlmkcow version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
"usage: vlmkcow [-h] [-f disk_image] cow_image [cow_size]\n"
printf("qemu-mkcow version " QEMU_VERSION ", Copyright (c) 2003 Fabrice Bellard\n"
"usage: qemu-mkcow [-h] [-f disk_image] cow_image [cow_size]\n"
"Create a Copy On Write disk image from an optional raw disk image\n"
"\n"
"-f disk_image set the raw disk image name\n"
@@ -101,13 +96,14 @@ void help(void)
int main(int argc, char **argv)
{
const char *image_filename, *cow_filename;
int cow_fd, c, nb_args;
int cow_fd, c, nb_args, simple_image;
int64_t image_size;
image_filename = NULL;
image_size = 0;
simple_image = 0;
for(;;) {
c = getopt(argc, argv, "hf:");
c = getopt(argc, argv, "hf:s");
if (c == -1)
break;
switch(c) {
@@ -117,6 +113,9 @@ int main(int argc, char **argv)
case 'f':
image_filename = optarg;
break;
case 's':
simple_image = 1;
break;
}
}
if (!image_filename)
@@ -131,12 +130,16 @@ int main(int argc, char **argv)
image_size = (int64_t)atoi(argv[optind + 1]) * 2 * 1024;
}
cow_fd = open(cow_filename, O_RDWR | O_CREAT | O_TRUNC, 0644);
cow_fd = open(cow_filename, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, 0644);
if (!cow_fd < 0)
return -1;
if (cow_create(cow_fd, image_filename, image_size) < 0) {
fprintf(stderr, "%s: error while formating\n", cow_filename);
exit(1);
if (simple_image) {
ftruncate64(cow_fd, image_size * 512);
} else {
if (cow_create(cow_fd, image_filename, image_size) < 0) {
fprintf(stderr, "%s: error while formating\n", cow_filename);
exit(1);
}
}
close(cow_fd);
return 0;

494
qemu-tech.texi Normal file
View File

@@ -0,0 +1,494 @@
\input texinfo @c -*- texinfo -*-
@iftex
@settitle QEMU Internals
@titlepage
@sp 7
@center @titlefont{QEMU Internals}
@sp 3
@end titlepage
@end iftex
@chapter Introduction
@section Features
QEMU is a FAST! processor emulator using a portable dynamic
translator.
QEMU has two operating modes:
@itemize @minus
@item
Full system emulation. In this mode, QEMU emulates a full system
(usually a PC), including a processor and various peripherials. It can
be used to launch an different Operating System without rebooting the
PC or to debug system code.
@item
User mode emulation (Linux host only). In this mode, QEMU can launch
Linux processes compiled for one CPU on another CPU. It can be used to
launch the Wine Windows API emulator (@url{http://www.winehq.org}) or
to ease cross-compilation and cross-debugging.
@end itemize
As QEMU requires no host kernel driver to run, it is very safe and
easy to use.
QEMU generic features:
@itemize
@item User space only or full system emulation.
@item Using dynamic translation to native code for reasonnable speed.
@item Working on x86 and PowerPC hosts. Being tested on ARM, Sparc32, Alpha and S390.
@item Self-modifying code support.
@item Precise exceptions support.
@item The virtual CPU is a library (@code{libqemu}) which can be used
in other projects (look at @file{qemu/tests/qruncom.c} to have an
example of user mode @code{libqemu} usage).
@end itemize
QEMU user mode emulation features:
@itemize
@item Generic Linux system call converter, including most ioctls.
@item clone() emulation using native CPU clone() to use Linux scheduler for threads.
@item Accurate signal handling by remapping host signals to target signals.
@end itemize
@end itemize
QEMU full system emulation features:
@itemize
@item QEMU can either use a full software MMU for maximum portability or use the host system call mmap() to simulate the target MMU.
@end itemize
@section x86 emulation
QEMU x86 target features:
@itemize
@item The virtual x86 CPU supports 16 bit and 32 bit addressing with segmentation.
LDT/GDT and IDT are emulated. VM86 mode is also supported to run DOSEMU.
@item Support of host page sizes bigger than 4KB in user mode emulation.
@item QEMU can emulate itself on x86.
@item An extensive Linux x86 CPU test program is included @file{tests/test-i386}.
It can be used to test other x86 virtual CPUs.
@end itemize
Current QEMU limitations:
@itemize
@item No SSE/MMX support (yet).
@item No x86-64 support.
@item IPC syscalls are missing.
@item The x86 segment limits and access rights are not tested at every
memory access (yet). Hopefully, very few OSes seem to rely on that for
normal use.
@item On non x86 host CPUs, @code{double}s are used instead of the non standard
10 byte @code{long double}s of x86 for floating point emulation to get
maximum performances.
@end itemize
@section ARM emulation
@itemize
@item Full ARM 7 user emulation.
@item NWFPE FPU support included in user Linux emulation.
@item Can run most ARM Linux binaries.
@end itemize
@section PowerPC emulation
@itemize
@item Full PowerPC 32 bit emulation, including priviledged instructions,
FPU and MMU.
@item Can run most PowerPC Linux binaries.
@end itemize
@section SPARC emulation
@itemize
@item SPARC V8 user support, except FPU instructions.
@item Can run some SPARC Linux binaries.
@end itemize
@chapter QEMU Internals
@section QEMU compared to other emulators
Like bochs [3], QEMU emulates an x86 CPU. But QEMU is much faster than
bochs as it uses dynamic compilation. Bochs is closely tied to x86 PC
emulation while QEMU can emulate several processors.
Like Valgrind [2], QEMU does user space emulation and dynamic
translation. Valgrind is mainly a memory debugger while QEMU has no
support for it (QEMU could be used to detect out of bound memory
accesses as Valgrind, but it has no support to track uninitialised data
as Valgrind does). The Valgrind dynamic translator generates better code
than QEMU (in particular it does register allocation) but it is closely
tied to an x86 host and target and has no support for precise exceptions
and system emulation.
EM86 [4] is the closest project to user space QEMU (and QEMU still uses
some of its code, in particular the ELF file loader). EM86 was limited
to an alpha host and used a proprietary and slow interpreter (the
interpreter part of the FX!32 Digital Win32 code translator [5]).
TWIN [6] is a Windows API emulator like Wine. It is less accurate than
Wine but includes a protected mode x86 interpreter to launch x86 Windows
executables. Such an approach as greater potential because most of the
Windows API is executed natively but it is far more difficult to develop
because all the data structures and function parameters exchanged
between the API and the x86 code must be converted.
User mode Linux [7] was the only solution before QEMU to launch a
Linux kernel as a process while not needing any host kernel
patches. However, user mode Linux requires heavy kernel patches while
QEMU accepts unpatched Linux kernels. The price to pay is that QEMU is
slower.
The new Plex86 [8] PC virtualizer is done in the same spirit as the
qemu-fast system emulator. It requires a patched Linux kernel to work
(you cannot launch the same kernel on your PC), but the patches are
really small. As it is a PC virtualizer (no emulation is done except
for some priveledged instructions), it has the potential of being
faster than QEMU. The downside is that a complicated (and potentially
unsafe) host kernel patch is needed.
The commercial PC Virtualizers (VMWare [9], VirtualPC [10], TwoOStwo
[11]) are faster than QEMU, but they all need specific, proprietary
and potentially unsafe host drivers. Moreover, they are unable to
provide cycle exact simulation as an emulator can.
@section Portable dynamic translation
QEMU is a dynamic translator. When it first encounters a piece of code,
it converts it to the host instruction set. Usually dynamic translators
are very complicated and highly CPU dependent. QEMU uses some tricks
which make it relatively easily portable and simple while achieving good
performances.
The basic idea is to split every x86 instruction into fewer simpler
instructions. Each simple instruction is implemented by a piece of C
code (see @file{target-i386/op.c}). Then a compile time tool
(@file{dyngen}) takes the corresponding object file (@file{op.o})
to generate a dynamic code generator which concatenates the simple
instructions to build a function (see @file{op.h:dyngen_code()}).
In essence, the process is similar to [1], but more work is done at
compile time.
A key idea to get optimal performances is that constant parameters can
be passed to the simple operations. For that purpose, dummy ELF
relocations are generated with gcc for each constant parameter. Then,
the tool (@file{dyngen}) can locate the relocations and generate the
appriopriate C code to resolve them when building the dynamic code.
That way, QEMU is no more difficult to port than a dynamic linker.
To go even faster, GCC static register variables are used to keep the
state of the virtual CPU.
@section Register allocation
Since QEMU uses fixed simple instructions, no efficient register
allocation can be done. However, because RISC CPUs have a lot of
register, most of the virtual CPU state can be put in registers without
doing complicated register allocation.
@section Condition code optimisations
Good CPU condition codes emulation (@code{EFLAGS} register on x86) is a
critical point to get good performances. QEMU uses lazy condition code
evaluation: instead of computing the condition codes after each x86
instruction, it just stores one operand (called @code{CC_SRC}), the
result (called @code{CC_DST}) and the type of operation (called
@code{CC_OP}).
@code{CC_OP} is almost never explicitely set in the generated code
because it is known at translation time.
In order to increase performances, a backward pass is performed on the
generated simple instructions (see
@code{target-i386/translate.c:optimize_flags()}). When it can be proved that
the condition codes are not needed by the next instructions, no
condition codes are computed at all.
@section CPU state optimisations
The x86 CPU has many internal states which change the way it evaluates
instructions. In order to achieve a good speed, the translation phase
considers that some state information of the virtual x86 CPU cannot
change in it. For example, if the SS, DS and ES segments have a zero
base, then the translator does not even generate an addition for the
segment base.
[The FPU stack pointer register is not handled that way yet].
@section Translation cache
A 16 MByte cache holds the most recently used translations. For
simplicity, it is completely flushed when it is full. A translation unit
contains just a single basic block (a block of x86 instructions
terminated by a jump or by a virtual CPU state change which the
translator cannot deduce statically).
@section Direct block chaining
After each translated basic block is executed, QEMU uses the simulated
Program Counter (PC) and other cpu state informations (such as the CS
segment base value) to find the next basic block.
In order to accelerate the most common cases where the new simulated PC
is known, QEMU can patch a basic block so that it jumps directly to the
next one.
The most portable code uses an indirect jump. An indirect jump makes
it easier to make the jump target modification atomic. On some host
architectures (such as x86 or PowerPC), the @code{JUMP} opcode is
directly patched so that the block chaining has no overhead.
@section Self-modifying code and translated code invalidation
Self-modifying code is a special challenge in x86 emulation because no
instruction cache invalidation is signaled by the application when code
is modified.
When translated code is generated for a basic block, the corresponding
host page is write protected if it is not already read-only (with the
system call @code{mprotect()}). Then, if a write access is done to the
page, Linux raises a SEGV signal. QEMU then invalidates all the
translated code in the page and enables write accesses to the page.
Correct translated code invalidation is done efficiently by maintaining
a linked list of every translated block contained in a given page. Other
linked lists are also maintained to undo direct block chaining.
Although the overhead of doing @code{mprotect()} calls is important,
most MSDOS programs can be emulated at reasonnable speed with QEMU and
DOSEMU.
Note that QEMU also invalidates pages of translated code when it detects
that memory mappings are modified with @code{mmap()} or @code{munmap()}.
When using a software MMU, the code invalidation is more efficient: if
a given code page is invalidated too often because of write accesses,
then a bitmap representing all the code inside the page is
built. Every store into that page checks the bitmap to see if the code
really needs to be invalidated. It avoids invalidating the code when
only data is modified in the page.
@section Exception support
longjmp() is used when an exception such as division by zero is
encountered.
The host SIGSEGV and SIGBUS signal handlers are used to get invalid
memory accesses. The exact CPU state can be retrieved because all the
x86 registers are stored in fixed host registers. The simulated program
counter is found by retranslating the corresponding basic block and by
looking where the host program counter was at the exception point.
The virtual CPU cannot retrieve the exact @code{EFLAGS} register because
in some cases it is not computed because of condition code
optimisations. It is not a big concern because the emulated code can
still be restarted in any cases.
@section MMU emulation
For system emulation, QEMU uses the mmap() system call to emulate the
target CPU MMU. It works as long the emulated OS does not use an area
reserved by the host OS (such as the area above 0xc0000000 on x86
Linux).
In order to be able to launch any OS, QEMU also supports a soft
MMU. In that mode, the MMU virtual to physical address translation is
done at every memory access. QEMU uses an address translation cache to
speed up the translation.
In order to avoid flushing the translated code each time the MMU
mappings change, QEMU uses a physically indexed translation cache. It
means that each basic block is indexed with its physical address.
When MMU mappings change, only the chaining of the basic blocks is
reset (i.e. a basic block can no longer jump directly to another one).
@section Hardware interrupts
In order to be faster, QEMU does not check at every basic block if an
hardware interrupt is pending. Instead, the user must asynchrously
call a specific function to tell that an interrupt is pending. This
function resets the chaining of the currently executing basic
block. It ensures that the execution will return soon in the main loop
of the CPU emulator. Then the main loop can test if the interrupt is
pending and handle it.
@section User emulation specific details
@subsection Linux system call translation
QEMU includes a generic system call translator for Linux. It means that
the parameters of the system calls can be converted to fix the
endianness and 32/64 bit issues. The IOCTLs are converted with a generic
type description system (see @file{ioctls.h} and @file{thunk.c}).
QEMU supports host CPUs which have pages bigger than 4KB. It records all
the mappings the process does and try to emulated the @code{mmap()}
system calls in cases where the host @code{mmap()} call would fail
because of bad page alignment.
@subsection Linux signals
Normal and real-time signals are queued along with their information
(@code{siginfo_t}) as it is done in the Linux kernel. Then an interrupt
request is done to the virtual CPU. When it is interrupted, one queued
signal is handled by generating a stack frame in the virtual CPU as the
Linux kernel does. The @code{sigreturn()} system call is emulated to return
from the virtual signal handler.
Some signals (such as SIGALRM) directly come from the host. Other
signals are synthetized from the virtual CPU exceptions such as SIGFPE
when a division by zero is done (see @code{main.c:cpu_loop()}).
The blocked signal mask is still handled by the host Linux kernel so
that most signal system calls can be redirected directly to the host
Linux kernel. Only the @code{sigaction()} and @code{sigreturn()} system
calls need to be fully emulated (see @file{signal.c}).
@subsection clone() system call and threads
The Linux clone() system call is usually used to create a thread. QEMU
uses the host clone() system call so that real host threads are created
for each emulated thread. One virtual CPU instance is created for each
thread.
The virtual x86 CPU atomic operations are emulated with a global lock so
that their semantic is preserved.
Note that currently there are still some locking issues in QEMU. In
particular, the translated cache flush is not protected yet against
reentrancy.
@subsection Self-virtualization
QEMU was conceived so that ultimately it can emulate itself. Although
it is not very useful, it is an important test to show the power of the
emulator.
Achieving self-virtualization is not easy because there may be address
space conflicts. QEMU solves this problem by being an executable ELF
shared object as the ld-linux.so ELF interpreter. That way, it can be
relocated at load time.
@section Bibliography
@table @asis
@item [1]
@url{http://citeseer.nj.nec.com/piumarta98optimizing.html}, Optimizing
direct threaded code by selective inlining (1998) by Ian Piumarta, Fabio
Riccardi.
@item [2]
@url{http://developer.kde.org/~sewardj/}, Valgrind, an open-source
memory debugger for x86-GNU/Linux, by Julian Seward.
@item [3]
@url{http://bochs.sourceforge.net/}, the Bochs IA-32 Emulator Project,
by Kevin Lawton et al.
@item [4]
@url{http://www.cs.rose-hulman.edu/~donaldlf/em86/index.html}, the EM86
x86 emulator on Alpha-Linux.
@item [5]
@url{http://www.usenix.org/publications/library/proceedings/usenix-nt97/full_papers/chernoff/chernoff.pdf},
DIGITAL FX!32: Running 32-Bit x86 Applications on Alpha NT, by Anton
Chernoff and Ray Hookway.
@item [6]
@url{http://www.willows.com/}, Windows API library emulation from
Willows Software.
@item [7]
@url{http://user-mode-linux.sourceforge.net/},
The User-mode Linux Kernel.
@item [8]
@url{http://www.plex86.org/},
The new Plex86 project.
@item [9]
@url{http://www.vmware.com/},
The VMWare PC virtualizer.
@item [10]
@url{http://www.microsoft.com/windowsxp/virtualpc/},
The VirtualPC PC virtualizer.
@item [11]
@url{http://www.twoostwo.org/},
The TwoOStwo PC virtualizer.
@end table
@chapter Regression Tests
In the directory @file{tests/}, various interesting testing programs
are available. There are used for regression testing.
@section @file{test-i386}
This program executes most of the 16 bit and 32 bit x86 instructions and
generates a text output. It can be compared with the output obtained with
a real CPU or another emulator. The target @code{make test} runs this
program and a @code{diff} on the generated output.
The Linux system call @code{modify_ldt()} is used to create x86 selectors
to test some 16 bit addressing and 32 bit with segmentation cases.
The Linux system call @code{vm86()} is used to test vm86 emulation.
Various exceptions are raised to test most of the x86 user space
exception reporting.
@section @file{linux-test}
This program tests various Linux system calls. It is used to verify
that the system call parameters are correctly converted between target
and host CPUs.
@section @file{qruncom.c}
Example of usage of @code{libqemu} to emulate a user mode i386 CPU.

515
sdl.c Normal file
View File

@@ -0,0 +1,515 @@
/*
* QEMU SDL display driver
*
* Copyright (c) 2003 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"
#include <SDL.h>
#ifndef _WIN32
#include <signal.h>
#endif
#if defined(__APPLE__)
#define CONFIG_SDL_GENERIC_KBD
#endif
static SDL_Surface *screen;
static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
static int last_vm_running;
static int gui_saved_grab;
static int gui_fullscreen;
static int gui_key_modifier_pressed;
static int gui_keysym;
static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
{
// printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
SDL_UpdateRect(screen, x, y, w, h);
}
static void sdl_resize(DisplayState *ds, int w, int h)
{
int flags;
// printf("resizing to %d %d\n", w, h);
flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
flags |= SDL_RESIZABLE;
if (gui_fullscreen)
flags |= SDL_FULLSCREEN;
screen = SDL_SetVideoMode(w, h, 0, flags);
if (!screen) {
fprintf(stderr, "Could not open SDL display\n");
exit(1);
}
ds->data = screen->pixels;
ds->linesize = screen->pitch;
ds->depth = screen->format->BitsPerPixel;
}
#ifdef CONFIG_SDL_GENERIC_KBD
/* XXX: use keymap tables defined in the VNC patch because the
following code suppose you have a US keyboard. */
static const uint8_t scancodes[SDLK_LAST] = {
[SDLK_ESCAPE] = 0x01,
[SDLK_1] = 0x02,
[SDLK_2] = 0x03,
[SDLK_3] = 0x04,
[SDLK_4] = 0x05,
[SDLK_5] = 0x06,
[SDLK_6] = 0x07,
[SDLK_7] = 0x08,
[SDLK_8] = 0x09,
[SDLK_9] = 0x0a,
[SDLK_0] = 0x0b,
[SDLK_MINUS] = 0x0c,
[SDLK_EQUALS] = 0x0d,
[SDLK_BACKSPACE] = 0x0e,
[SDLK_TAB] = 0x0f,
[SDLK_q] = 0x10,
[SDLK_w] = 0x11,
[SDLK_e] = 0x12,
[SDLK_r] = 0x13,
[SDLK_t] = 0x14,
[SDLK_y] = 0x15,
[SDLK_u] = 0x16,
[SDLK_i] = 0x17,
[SDLK_o] = 0x18,
[SDLK_p] = 0x19,
[SDLK_LEFTBRACKET] = 0x1a,
[SDLK_RIGHTBRACKET] = 0x1b,
[SDLK_RETURN] = 0x1c,
[SDLK_LCTRL] = 0x1d,
[SDLK_a] = 0x1e,
[SDLK_s] = 0x1f,
[SDLK_d] = 0x20,
[SDLK_f] = 0x21,
[SDLK_g] = 0x22,
[SDLK_h] = 0x23,
[SDLK_j] = 0x24,
[SDLK_k] = 0x25,
[SDLK_l] = 0x26,
[SDLK_SEMICOLON] = 0x27,
[SDLK_QUOTE] = 0x28,
[SDLK_BACKQUOTE] = 0x29,
[SDLK_LSHIFT] = 0x2a,
[SDLK_BACKSLASH] = 0x2b,
[SDLK_z] = 0x2c,
[SDLK_x] = 0x2d,
[SDLK_c] = 0x2e,
[SDLK_v] = 0x2f,
[SDLK_b] = 0x30,
[SDLK_n] = 0x31,
[SDLK_m] = 0x32,
[SDLK_COMMA] = 0x33,
[SDLK_PERIOD] = 0x34,
[SDLK_SLASH] = 0x35,
[SDLK_KP_MULTIPLY] = 0x37,
[SDLK_LALT] = 0x38,
[SDLK_SPACE] = 0x39,
[SDLK_CAPSLOCK] = 0x3a,
[SDLK_F1] = 0x3b,
[SDLK_F2] = 0x3c,
[SDLK_F3] = 0x3d,
[SDLK_F4] = 0x3e,
[SDLK_F5] = 0x3f,
[SDLK_F6] = 0x40,
[SDLK_F7] = 0x41,
[SDLK_F8] = 0x42,
[SDLK_F9] = 0x43,
[SDLK_F10] = 0x44,
[SDLK_NUMLOCK] = 0x45,
[SDLK_SCROLLOCK] = 0x46,
[SDLK_KP7] = 0x47,
[SDLK_KP8] = 0x48,
[SDLK_KP9] = 0x49,
[SDLK_KP_MINUS] = 0x4a,
[SDLK_KP4] = 0x4b,
[SDLK_KP5] = 0x4c,
[SDLK_KP6] = 0x4d,
[SDLK_KP_PLUS] = 0x4e,
[SDLK_KP1] = 0x4f,
[SDLK_KP2] = 0x50,
[SDLK_KP3] = 0x51,
[SDLK_KP0] = 0x52,
[SDLK_KP_PERIOD] = 0x53,
[SDLK_PRINT] = 0x54,
[SDLK_LMETA] = 0x56,
[SDLK_KP_ENTER] = 0x9c,
[SDLK_KP_DIVIDE] = 0xb5,
[SDLK_UP] = 0xc8,
[SDLK_DOWN] = 0xd0,
[SDLK_RIGHT] = 0xcd,
[SDLK_LEFT] = 0xcb,
[SDLK_INSERT] = 0xd2,
[SDLK_HOME] = 0xc7,
[SDLK_END] = 0xcf,
[SDLK_PAGEUP] = 0xc9,
[SDLK_PAGEDOWN] = 0xd1,
[SDLK_DELETE] = 0xd3,
};
static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
{
return scancodes[ev->keysym.sym];
}
#elif defined(_WIN32)
static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
{
return ev->keysym.scancode;
}
#else
static const uint8_t x_keycode_to_pc_keycode[61] = {
0xc7, /* 97 Home */
0xc8, /* 98 Up */
0xc9, /* 99 PgUp */
0xcb, /* 100 Left */
0x4c, /* 101 KP-5 */
0xcd, /* 102 Right */
0xcf, /* 103 End */
0xd0, /* 104 Down */
0xd1, /* 105 PgDn */
0xd2, /* 106 Ins */
0xd3, /* 107 Del */
0x9c, /* 108 Enter */
0x9d, /* 109 Ctrl-R */
0x0, /* 110 Pause */
0xb7, /* 111 Print */
0xb5, /* 112 Divide */
0xb8, /* 113 Alt-R */
0xc6, /* 114 Break */
0x0, /* 115 */
0x0, /* 116 */
0x0, /* 117 */
0x0, /* 118 */
0x0, /* 119 */
0x70, /* 120 Hiragana_Katakana */
0x0, /* 121 */
0x0, /* 122 */
0x73, /* 123 backslash */
0x0, /* 124 */
0x0, /* 125 */
0x0, /* 126 */
0x0, /* 127 */
0x0, /* 128 */
0x79, /* 129 Henkan */
0x0, /* 130 */
0x7b, /* 131 Muhenkan */
0x0, /* 132 */
0x7d, /* 133 Yen */
0x0, /* 134 */
0x0, /* 135 */
0x47, /* 136 KP_7 */
0x48, /* 137 KP_8 */
0x49, /* 138 KP_9 */
0x4b, /* 139 KP_4 */
0x4c, /* 140 KP_5 */
0x4d, /* 141 KP_6 */
0x4f, /* 142 KP_1 */
0x50, /* 143 KP_2 */
0x51, /* 144 KP_3 */
0x52, /* 145 KP_0 */
0x53, /* 146 KP_. */
0x47, /* 147 KP_HOME */
0x48, /* 148 KP_UP */
0x49, /* 149 KP_PgUp */
0x4b, /* 150 KP_Left */
0x4c, /* 151 KP_ */
0x4d, /* 152 KP_Right */
0x4f, /* 153 KP_End */
0x50, /* 154 KP_Down */
0x51, /* 155 KP_PgDn */
0x52, /* 156 KP_Ins */
0x53, /* 157 KP_Del */
};
static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
{
int keycode;
keycode = ev->keysym.scancode;
if (keycode < 9) {
keycode = 0;
} else if (keycode < 97) {
keycode -= 8; /* just an offset */
} else if (keycode < 158) {
/* use conversion table */
keycode = x_keycode_to_pc_keycode[keycode - 97];
} else {
keycode = 0;
}
return keycode;
}
#endif
static void sdl_process_key(SDL_KeyboardEvent *ev)
{
int keycode, v, i;
static uint8_t modifiers_state[256];
if (ev->keysym.sym == SDLK_PAUSE) {
/* specific case */
v = 0;
if (ev->type == SDL_KEYUP)
v |= 0x80;
kbd_put_keycode(0xe1);
kbd_put_keycode(0x1d | v);
kbd_put_keycode(0x45 | v);
return;
}
/* XXX: not portable, but avoids complicated mappings */
keycode = sdl_keyevent_to_keycode(ev);
switch(keycode) {
case 0x00:
/* sent when leaving window: reset the modifiers state */
for(i = 0; i < 256; i++) {
if (modifiers_state[i]) {
if (i & 0x80)
kbd_put_keycode(0xe0);
kbd_put_keycode(i | 0x80);
}
}
return;
case 0x2a: /* Left Shift */
case 0x36: /* Right Shift */
case 0x1d: /* Left CTRL */
case 0x9d: /* Right CTRL */
case 0x38: /* Left ALT */
case 0xb8: /* Right ALT */
if (ev->type == SDL_KEYUP)
modifiers_state[keycode] = 0;
else
modifiers_state[keycode] = 1;
break;
case 0x45: /* num lock */
case 0x3a: /* caps lock */
/* SDL does not send the key up event, so we generate it */
kbd_put_keycode(keycode);
kbd_put_keycode(keycode | 0x80);
return;
}
/* now send the key code */
if (keycode & 0x80)
kbd_put_keycode(0xe0);
if (ev->type == SDL_KEYUP)
kbd_put_keycode(keycode | 0x80);
else
kbd_put_keycode(keycode & 0x7f);
}
static void sdl_update_caption(void)
{
char buf[1024];
strcpy(buf, "QEMU");
if (!vm_running) {
strcat(buf, " [Stopped]");
}
if (gui_grab) {
strcat(buf, " - Press Ctrl-Shift to exit grab");
}
SDL_WM_SetCaption(buf, "QEMU");
}
static void sdl_grab_start(void)
{
SDL_ShowCursor(0);
SDL_WM_GrabInput(SDL_GRAB_ON);
/* dummy read to avoid moving the mouse */
SDL_GetRelativeMouseState(NULL, NULL);
gui_grab = 1;
sdl_update_caption();
}
static void sdl_grab_end(void)
{
SDL_WM_GrabInput(SDL_GRAB_OFF);
SDL_ShowCursor(1);
gui_grab = 0;
sdl_update_caption();
}
static void sdl_send_mouse_event(void)
{
int dx, dy, dz, state, buttons;
state = SDL_GetRelativeMouseState(&dx, &dy);
buttons = 0;
if (state & SDL_BUTTON(SDL_BUTTON_LEFT))
buttons |= MOUSE_EVENT_LBUTTON;
if (state & SDL_BUTTON(SDL_BUTTON_RIGHT))
buttons |= MOUSE_EVENT_RBUTTON;
if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))
buttons |= MOUSE_EVENT_MBUTTON;
/* XXX: test wheel */
dz = 0;
#ifdef SDL_BUTTON_WHEELUP
if (state & SDL_BUTTON(SDL_BUTTON_WHEELUP))
dz--;
if (state & SDL_BUTTON(SDL_BUTTON_WHEELDOWN))
dz++;
#endif
kbd_mouse_event(dx, dy, dz, buttons);
}
static void toggle_full_screen(DisplayState *ds)
{
gui_fullscreen = !gui_fullscreen;
sdl_resize(ds, screen->w, screen->h);
if (gui_fullscreen) {
gui_saved_grab = gui_grab;
sdl_grab_start();
} else {
if (!gui_saved_grab)
sdl_grab_end();
}
vga_invalidate_display();
vga_update_display();
}
static void sdl_refresh(DisplayState *ds)
{
SDL_Event ev1, *ev = &ev1;
int mod_state;
if (last_vm_running != vm_running) {
last_vm_running = vm_running;
sdl_update_caption();
}
vga_update_display();
while (SDL_PollEvent(ev)) {
switch (ev->type) {
case SDL_VIDEOEXPOSE:
sdl_update(ds, 0, 0, screen->w, screen->h);
break;
case SDL_KEYDOWN:
case SDL_KEYUP:
if (ev->type == SDL_KEYDOWN) {
mod_state = (SDL_GetModState() & (KMOD_LSHIFT | KMOD_LCTRL)) ==
(KMOD_LSHIFT | KMOD_LCTRL);
gui_key_modifier_pressed = mod_state;
if (gui_key_modifier_pressed &&
ev->key.keysym.sym == SDLK_f) {
gui_keysym = ev->key.keysym.sym;
}
} else if (ev->type == SDL_KEYUP) {
mod_state = (SDL_GetModState() & (KMOD_LSHIFT | KMOD_LCTRL));
if (!mod_state) {
if (gui_key_modifier_pressed) {
switch(gui_keysym) {
case SDLK_f:
toggle_full_screen(ds);
break;
case 0:
/* exit/enter grab if pressing Ctrl-Shift */
if (!gui_grab)
sdl_grab_start();
else
sdl_grab_end();
break;
}
gui_key_modifier_pressed = 0;
gui_keysym = 0;
}
}
}
sdl_process_key(&ev->key);
break;
case SDL_QUIT:
qemu_system_shutdown_request();
break;
case SDL_MOUSEMOTION:
if (gui_grab) {
sdl_send_mouse_event();
}
break;
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
{
SDL_MouseButtonEvent *bev = &ev->button;
if (!gui_grab) {
if (ev->type == SDL_MOUSEBUTTONDOWN &&
(bev->state & SDL_BUTTON_LMASK)) {
/* start grabbing all events */
sdl_grab_start();
}
} else {
sdl_send_mouse_event();
}
}
break;
case SDL_ACTIVEEVENT:
if (gui_grab && (ev->active.gain & SDL_ACTIVEEVENTMASK) == 0) {
sdl_grab_end();
}
break;
default:
break;
}
}
}
static void sdl_cleanup(void)
{
SDL_Quit();
}
void sdl_display_init(DisplayState *ds)
{
int flags;
flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
if (SDL_Init (flags)) {
fprintf(stderr, "Could not initialize SDL - exiting\n");
exit(1);
}
#ifndef _WIN32
/* NOTE: we still want Ctrl-C to work, so we undo the SDL redirections */
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
#endif
ds->dpy_update = sdl_update;
ds->dpy_resize = sdl_resize;
ds->dpy_refresh = sdl_refresh;
sdl_resize(ds, 640, 400);
sdl_update_caption();
SDL_EnableKeyRepeat(250, 50);
gui_grab = 0;
atexit(sdl_cleanup);
}

64
slirp/COPYRIGHT Normal file
View File

@@ -0,0 +1,64 @@
Slirp was written by Danny Gasparovski.
Copyright (c), 1995,1996 All Rights Reserved.
Slirp is maintained by Kelly Price <tygris+slirp@erols.com>
Slirp is free software; "free" as in you don't have to pay for it, and you
are free to do whatever you want with it. I do not accept any donations,
monetary or otherwise, for Slirp. Instead, I would ask you to pass this
potential donation to your favorite charity. In fact, I encourage
*everyone* who finds Slirp useful to make a small donation to their
favorite charity (for example, GreenPeace). This is not a requirement, but
a suggestion from someone who highly values the service they provide.
The copyright terms and conditions:
---BEGIN---
Copyright (c) 1995,1996 Danny Gasparovski. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgment:
This product includes software developed by Danny Gasparovski.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
DANNY GASPAROVSKI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---END---
This basically means you can do anything you want with the software, except
1) call it your own, and 2) claim warranty on it. There is no warranty for
this software. None. Nada. If you lose a million dollars while using
Slirp, that's your loss not mine. So, ***USE AT YOUR OWN RISK!***.
If these conditions cannot be met due to legal restrictions (E.g. where it
is against the law to give out Software without warranty), you must cease
using the software and delete all copies you have.
Slirp uses code that is copyrighted by the following people/organizations:
Juha Pirkola.
Gregory M. Christy.
The Regents of the University of California.
Carnegie Mellon University.
The Australian National University.
RSA Data Security, Inc.
Please read the top of each source file for the details on the various
copyrights.

240
slirp/bootp.c Normal file
View File

@@ -0,0 +1,240 @@
/*
* QEMU BOOTP/DHCP server
*
* Copyright (c) 2004 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 <slirp.h>
/* XXX: only DHCP is supported */
#define NB_ADDR 16
#define START_ADDR 15
#define LEASE_TIME (24 * 3600)
typedef struct {
uint8_t allocated;
uint8_t macaddr[6];
} BOOTPClient;
BOOTPClient bootp_clients[NB_ADDR];
static const uint8_t rfc1533_cookie[] = { RFC1533_COOKIE };
#ifdef DEBUG
#define dprintf(fmt, args...) \
if (slirp_debug & DBG_CALL) { fprintf(dfd, fmt, ## args); fflush(dfd); }
#else
#define dprintf(fmt, args...)
#endif
static BOOTPClient *get_new_addr(struct in_addr *paddr)
{
BOOTPClient *bc;
int i;
for(i = 0; i < NB_ADDR; i++) {
if (!bootp_clients[i].allocated)
goto found;
}
return NULL;
found:
bc = &bootp_clients[i];
bc->allocated = 1;
paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
return bc;
}
static BOOTPClient *find_addr(struct in_addr *paddr, const uint8_t *macaddr)
{
BOOTPClient *bc;
int i;
for(i = 0; i < NB_ADDR; i++) {
if (!memcmp(macaddr, bootp_clients[i].macaddr, 6))
goto found;
}
return NULL;
found:
bc = &bootp_clients[i];
bc->allocated = 1;
paddr->s_addr = htonl(ntohl(special_addr.s_addr) | (i + START_ADDR));
return bc;
}
static void dhcp_decode(const uint8_t *buf, int size,
int *pmsg_type)
{
const uint8_t *p, *p_end;
int len, tag;
*pmsg_type = 0;
p = buf;
p_end = buf + size;
if (size < 5)
return;
if (memcmp(p, rfc1533_cookie, 4) != 0)
return;
p += 4;
while (p < p_end) {
tag = p[0];
if (tag == RFC1533_PAD) {
p++;
} else if (tag == RFC1533_END) {
break;
} else {
p++;
if (p >= p_end)
break;
len = *p++;
dprintf("dhcp: tag=0x%02x len=%d\n", tag, len);
switch(tag) {
case RFC2132_MSG_TYPE:
if (len >= 1)
*pmsg_type = p[0];
break;
default:
break;
}
p += len;
}
}
}
static void bootp_reply(struct bootp_t *bp)
{
BOOTPClient *bc;
struct mbuf *m;
struct bootp_t *rbp;
struct sockaddr_in saddr, daddr;
struct in_addr dns_addr;
int dhcp_msg_type, val;
uint8_t *q;
/* extract exact DHCP msg type */
dhcp_decode(bp->bp_vend, DHCP_OPT_LEN, &dhcp_msg_type);
dprintf("bootp packet op=%d msgtype=%d\n", bp->bp_op, dhcp_msg_type);
if (dhcp_msg_type != DHCPDISCOVER &&
dhcp_msg_type != DHCPREQUEST)
return;
/* XXX: this is a hack to get the client mac address */
memcpy(client_ethaddr, bp->bp_hwaddr, 6);
if ((m = m_get()) == NULL)
return;
m->m_data += if_maxlinkhdr;
rbp = (struct bootp_t *)m->m_data;
m->m_data += sizeof(struct udpiphdr);
memset(rbp, 0, sizeof(struct bootp_t));
if (dhcp_msg_type == DHCPDISCOVER) {
bc = get_new_addr(&daddr.sin_addr);
if (!bc) {
dprintf("no address left\n");
return;
}
memcpy(bc->macaddr, client_ethaddr, 6);
} else {
bc = find_addr(&daddr.sin_addr, bp->bp_hwaddr);
if (!bc) {
dprintf("no address assigned\n");
return;
}
}
dprintf("offered addr=%08x\n", ntohl(daddr.sin_addr.s_addr));
saddr.sin_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_ALIAS);
saddr.sin_port = htons(BOOTP_SERVER);
daddr.sin_port = htons(BOOTP_CLIENT);
rbp->bp_op = BOOTP_REPLY;
rbp->bp_xid = bp->bp_xid;
rbp->bp_htype = 1;
rbp->bp_hlen = 6;
memcpy(rbp->bp_hwaddr, bp->bp_hwaddr, 6);
rbp->bp_yiaddr = daddr.sin_addr; /* IP address */
q = rbp->bp_vend;
memcpy(q, rfc1533_cookie, 4);
q += 4;
if (dhcp_msg_type == DHCPDISCOVER) {
*q++ = RFC2132_MSG_TYPE;
*q++ = 1;
*q++ = DHCPOFFER;
} else if (dhcp_msg_type == DHCPREQUEST) {
*q++ = RFC2132_MSG_TYPE;
*q++ = 1;
*q++ = DHCPACK;
}
if (dhcp_msg_type == DHCPDISCOVER ||
dhcp_msg_type == DHCPREQUEST) {
*q++ = RFC2132_SRV_ID;
*q++ = 4;
memcpy(q, &saddr.sin_addr, 4);
q += 4;
*q++ = RFC1533_NETMASK;
*q++ = 4;
*q++ = 0xff;
*q++ = 0xff;
*q++ = 0xff;
*q++ = 0x00;
*q++ = RFC1533_GATEWAY;
*q++ = 4;
memcpy(q, &saddr.sin_addr, 4);
q += 4;
*q++ = RFC1533_DNS;
*q++ = 4;
dns_addr.s_addr = htonl(ntohl(special_addr.s_addr) | CTL_DNS);
memcpy(q, &dns_addr, 4);
q += 4;
*q++ = RFC2132_LEASE_TIME;
*q++ = 4;
val = htonl(LEASE_TIME);
memcpy(q, &val, 4);
q += 4;
}
*q++ = RFC1533_END;
m->m_len = sizeof(struct bootp_t) -
sizeof(struct ip) - sizeof(struct udphdr);
udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY);
}
void bootp_input(struct mbuf *m)
{
struct bootp_t *bp = (struct bootp_t *)m->m_data;
if (bp->bp_op == BOOTP_REQUEST) {
bootp_reply(bp);
}
}

Some files were not shown because too many files have changed in this diff Show More