summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cvsignore13
-rw-r--r--Changelog35
-rw-r--r--Makefile43
-rw-r--r--Makefile.target237
-rw-r--r--TODO2
-rw-r--r--a.out.h104
-rw-r--r--aes.c8
-rw-r--r--alpha-dis.c2
-rw-r--r--arm-dis.c160
-rw-r--r--arm-semi.c96
-rw-r--r--audio/alsaaudio.c62
-rw-r--r--audio/audio.c118
-rw-r--r--audio/audio.h4
-rw-r--r--audio/audio_int.h4
-rw-r--r--audio/audio_template.h4
-rw-r--r--audio/coreaudio.c5
-rw-r--r--audio/mixeng.c95
-rw-r--r--audio/mixeng.h4
-rw-r--r--audio/ossaudio.c5
-rw-r--r--audio/sdlaudio.c18
-rw-r--r--audio/wavaudio.c8
-rw-r--r--audio/wavcapture.c6
-rw-r--r--block-bochs.c34
-rw-r--r--block-cloop.c16
-rw-r--r--block-cow.c32
-rw-r--r--block-dmg.c14
-rw-r--r--block-parallels.c176
-rw-r--r--block-qcow.c116
-rw-r--r--block-qcow2.c266
-rw-r--r--block-raw.c146
-rw-r--r--block-vmdk.c187
-rw-r--r--block-vpc.c20
-rw-r--r--block-vvfat.c165
-rw-r--r--block.c101
-rw-r--r--block_int.h30
-rw-r--r--bswap.h4
-rw-r--r--cocoa.m221
-rwxr-xr-xconfigure420
-rw-r--r--console.c140
-rw-r--r--cpu-all.h152
-rw-r--r--cpu-defs.h39
-rw-r--r--cpu-exec.c431
-rw-r--r--cutils.c4
-rw-r--r--d3des.c434
-rw-r--r--d3des.h51
-rw-r--r--darwin-user/main.c576
-rw-r--r--darwin-user/mmap.c2
-rw-r--r--darwin-user/syscall.c50
-rw-r--r--darwin-user/syscalls.h4
-rw-r--r--dis-asm.h17
-rw-r--r--disas.c40
-rw-r--r--dyngen-exec.h86
-rw-r--r--dyngen.c647
-rw-r--r--dyngen.h80
-rw-r--r--elf.h5
-rw-r--r--elf_ops.h24
-rw-r--r--exec-all.h160
-rw-r--r--exec.c739
-rw-r--r--fpu/softfloat-native.c125
-rw-r--r--fpu/softfloat-native.h35
-rw-r--r--fpu/softfloat-specialize.h48
-rw-r--r--fpu/softfloat.c48
-rw-r--r--fpu/softfloat.h13
-rw-r--r--gdbstub.c264
-rw-r--r--gdbstub.h5
-rw-r--r--host-utils.c75
-rw-r--r--hpet.h22
-rw-r--r--hw/acpi.c89
-rw-r--r--hw/adb.c24
-rw-r--r--hw/adlib.c2
-rw-r--r--hw/ads7846.c167
-rw-r--r--hw/alpha_palcode.c1099
-rw-r--r--hw/an5206.c91
-rw-r--r--hw/apb_pci.c14
-rw-r--r--hw/apic.c43
-rw-r--r--hw/arm_boot.c146
-rw-r--r--hw/arm_gic.c32
-rw-r--r--hw/arm_pic.c45
-rw-r--r--hw/arm_pic.h8
-rw-r--r--hw/arm_sysctl.c6
-rw-r--r--hw/arm_timer.c202
-rw-r--r--hw/cdrom.c22
-rw-r--r--hw/cirrus_vga.c177
-rw-r--r--hw/cirrus_vga_rop.h106
-rw-r--r--hw/cirrus_vga_rop2.h30
-rw-r--r--hw/cs4231.c6
-rw-r--r--hw/cuda.c70
-rw-r--r--hw/dma.c4
-rw-r--r--hw/ds1225y.c121
-rw-r--r--hw/ecc.c90
-rw-r--r--hw/eepro100.c1813
-rw-r--r--hw/eeprom93xx.c312
-rw-r--r--hw/eeprom93xx.h43
-rw-r--r--hw/es1370.c4
-rw-r--r--hw/esp.c83
-rw-r--r--hw/fdc.c153
-rw-r--r--hw/grackle_pci.c20
-rw-r--r--hw/gt64xxx.c663
-rw-r--r--hw/heathrow_pic.c18
-rw-r--r--hw/i2c.c148
-rw-r--r--hw/i2c.h67
-rw-r--r--hw/i8254.c22
-rw-r--r--hw/i8259.c64
-rw-r--r--hw/ide.c1281
-rw-r--r--hw/integratorcp.c108
-rw-r--r--hw/iommu.c121
-rw-r--r--hw/irq.c57
-rw-r--r--hw/irq.h21
-rw-r--r--hw/isa_mmio.c2
-rw-r--r--hw/jazz_led.c303
-rw-r--r--hw/lsi53c895a.c35
-rw-r--r--hw/m48t59.c107
-rw-r--r--hw/m48t59.h2
-rw-r--r--hw/max111x.c173
-rw-r--r--hw/max7310.c226
-rw-r--r--hw/mc146818rtc.c152
-rw-r--r--hw/mcf5206.c540
-rw-r--r--hw/mcf5208.c305
-rw-r--r--hw/mcf_fec.c456
-rw-r--r--hw/mcf_intc.c156
-rw-r--r--hw/mcf_uart.c306
-rw-r--r--hw/mips_int.c39
-rw-r--r--hw/mips_malta.c454
-rw-r--r--hw/mips_pica61.c180
-rw-r--r--hw/mips_r4k.c83
-rw-r--r--hw/mips_timer.c54
-rw-r--r--hw/nand.c650
-rw-r--r--hw/ne2000.c102
-rw-r--r--hw/omap.c2929
-rw-r--r--hw/omap.h596
-rw-r--r--hw/omap1_clk.c745
-rw-r--r--hw/omap_lcd_template.h172
-rw-r--r--hw/omap_lcdc.c499
-rw-r--r--hw/omap_mmc.c531
-rw-r--r--hw/openpic.c139
-rw-r--r--hw/palm.c140
-rw-r--r--hw/parallel.c516
-rw-r--r--hw/pc.c501
-rw-r--r--hw/pci.c90
-rw-r--r--hw/pci_host.h2
-rw-r--r--hw/pckbd.c114
-rw-r--r--hw/pcnet.c866
-rw-r--r--hw/pcspk.c2
-rw-r--r--hw/pflash_cfi02.c83
-rw-r--r--hw/piix_pci.c24
-rw-r--r--hw/pixel_ops.h53
-rw-r--r--hw/pl011.c22
-rw-r--r--hw/pl031.c219
-rw-r--r--hw/pl050.c43
-rw-r--r--hw/pl080.c16
-rw-r--r--hw/pl110.c18
-rw-r--r--hw/pl110_template.h4
-rw-r--r--hw/pl181.c466
-rw-r--r--hw/pl190.c22
-rw-r--r--hw/ppc.c1082
-rw-r--r--hw/ppc405.h126
-rw-r--r--hw/ppc405_boards.c630
-rw-r--r--hw/ppc405_uc.c3461
-rw-r--r--hw/ppc_chrp.c288
-rw-r--r--hw/ppc_prep.c111
-rw-r--r--hw/prep_pci.c16
-rw-r--r--hw/ps2.c19
-rw-r--r--hw/ptimer.c191
-rw-r--r--hw/pxa.h214
-rw-r--r--hw/pxa2xx.c2235
-rw-r--r--hw/pxa2xx_dma.c553
-rw-r--r--hw/pxa2xx_gpio.c338
-rw-r--r--hw/pxa2xx_lcd.c1049
-rw-r--r--hw/pxa2xx_mmci.c553
-rw-r--r--hw/pxa2xx_pcmcia.c225
-rw-r--r--hw/pxa2xx_pic.c317
-rw-r--r--hw/pxa2xx_template.h431
-rw-r--r--hw/pxa2xx_timer.c495
-rw-r--r--hw/r2d.c63
-rw-r--r--hw/realview.c47
-rw-r--r--hw/rtl8139.c93
-rw-r--r--hw/sb16.c24
-rw-r--r--hw/scsi-disk.c11
-rw-r--r--hw/sd.c1509
-rw-r--r--hw/sd.h82
-rw-r--r--hw/serial.c85
-rw-r--r--hw/sh7750.c504
-rw-r--r--hw/sh7750_regnames.c30
-rw-r--r--hw/sh7750_regs.h353
-rw-r--r--hw/sh_serial.c315
-rw-r--r--hw/sh_timer.c323
-rw-r--r--hw/shix.c13
-rw-r--r--hw/slavio_intctl.c212
-rw-r--r--hw/slavio_misc.c44
-rw-r--r--hw/slavio_serial.c209
-rw-r--r--hw/slavio_timer.c166
-rw-r--r--hw/smbus.c306
-rw-r--r--hw/smbus.h50
-rw-r--r--hw/smbus_eeprom.c50
-rw-r--r--hw/smc91c111.c18
-rw-r--r--hw/sparc32_dma.c108
-rw-r--r--hw/spitz.c1285
-rw-r--r--hw/sun4m.c471
-rw-r--r--hw/sun4u.c147
-rw-r--r--hw/tcx.c350
-rw-r--r--hw/unin_pci.c16
-rw-r--r--hw/usb-hid.c461
-rw-r--r--hw/usb-hub.c22
-rw-r--r--hw/usb-msd.c16
-rw-r--r--hw/usb-ohci.c152
-rw-r--r--hw/usb-uhci.c120
-rw-r--r--hw/usb-wacom.c412
-rw-r--r--hw/usb.c10
-rw-r--r--hw/usb.h23
-rw-r--r--hw/versatile_pci.c8
-rw-r--r--hw/versatilepb.c82
-rw-r--r--hw/vga.c381
-rw-r--r--hw/vga_int.h32
-rw-r--r--hw/vga_template.h82
-rw-r--r--hw/vmmouse.c288
-rw-r--r--hw/vmport.c96
-rw-r--r--hw/vmware_vga.c1193
-rw-r--r--hw/wm8750.c634
-rw-r--r--keymaps.c4
-rw-r--r--keymaps/common2
-rw-r--r--keymaps/de-ch18
-rw-r--r--keymaps/et10
-rw-r--r--keymaps/fr2
-rw-r--r--keymaps/is20
-rw-r--r--keymaps/modifiers6
-rw-r--r--keymaps/nl2
-rw-r--r--keymaps/sv8
-rw-r--r--kqemu.c79
-rw-r--r--kqemu.h6
-rw-r--r--linux-user/alpha/syscall.h41
-rw-r--r--linux-user/alpha/syscall_nr.h413
-rw-r--r--linux-user/alpha/target_signal.h29
-rw-r--r--linux-user/alpha/termbits.h265
-rw-r--r--linux-user/arm/syscall_nr.h31
-rw-r--r--linux-user/arm/target_signal.h29
-rw-r--r--linux-user/arm/termbits.h4
-rw-r--r--linux-user/elfload.c168
-rw-r--r--linux-user/errno_defs.h142
-rw-r--r--linux-user/flat.h2
-rw-r--r--linux-user/flatload.c50
-rw-r--r--linux-user/i386/syscall.h76
-rw-r--r--linux-user/i386/syscall_nr.h59
-rw-r--r--linux-user/i386/target_signal.h29
-rw-r--r--linux-user/i386/termbits.h15
-rw-r--r--linux-user/linuxload.c6
-rw-r--r--linux-user/m68k-semi.c216
-rw-r--r--linux-user/m68k-sim.c2
-rw-r--r--linux-user/m68k/syscall_nr.h39
-rw-r--r--linux-user/m68k/target_signal.h24
-rw-r--r--linux-user/m68k/termbits.h15
-rw-r--r--linux-user/main.c988
-rw-r--r--linux-user/mips/syscall.h205
-rw-r--r--linux-user/mips/syscall_nr.h387
-rw-r--r--linux-user/mips/target_signal.h29
-rw-r--r--linux-user/mips/termbits.h40
-rw-r--r--linux-user/mips64/syscall.h221
-rw-r--r--linux-user/mips64/syscall_nr.h284
-rw-r--r--linux-user/mips64/target_signal.h29
-rw-r--r--linux-user/mips64/termbits.h245
-rw-r--r--linux-user/mipsn32/syscall.h221
-rw-r--r--linux-user/mipsn32/syscall_nr.h288
-rw-r--r--linux-user/mipsn32/target_signal.h29
-rw-r--r--linux-user/mipsn32/termbits.h245
-rw-r--r--linux-user/mmap.c152
-rw-r--r--linux-user/path.c46
-rw-r--r--linux-user/ppc/syscall.h78
-rw-r--r--linux-user/ppc/syscall_nr.h55
-rw-r--r--linux-user/ppc/target_signal.h29
-rw-r--r--linux-user/ppc/termbits.h8
-rw-r--r--linux-user/ppc64/syscall.h130
-rw-r--r--linux-user/ppc64/syscall_nr.h313
-rw-r--r--linux-user/ppc64/target_signal.h29
-rw-r--r--linux-user/ppc64/termbits.h237
-rw-r--r--linux-user/qemu.h32
-rw-r--r--linux-user/sh4/syscall_nr.h40
-rw-r--r--linux-user/sh4/target_signal.h24
-rw-r--r--linux-user/sh4/termbits.h10
-rw-r--r--linux-user/signal.c426
-rw-r--r--linux-user/sparc/syscall_nr.h60
-rw-r--r--linux-user/sparc/target_signal.h36
-rw-r--r--linux-user/sparc/termbits.h3
-rw-r--r--linux-user/sparc64/syscall_nr.h31
-rw-r--r--linux-user/sparc64/target_signal.h36
-rw-r--r--linux-user/sparc64/termbits.h3
-rw-r--r--linux-user/syscall.c1405
-rw-r--r--linux-user/syscall_defs.h380
-rw-r--r--linux-user/syscall_types.h12
-rw-r--r--linux-user/vm86.c32
-rw-r--r--linux-user/x86_64/syscall.h92
-rw-r--r--linux-user/x86_64/syscall_nr.h286
-rw-r--r--linux-user/x86_64/target_signal.h29
-rw-r--r--linux-user/x86_64/termbits.h247
-rw-r--r--loader.c90
-rw-r--r--m68k-dis.c18
-rw-r--r--m68k-semi.c359
-rw-r--r--mips-dis.c3304
-rw-r--r--mips.ld225
-rw-r--r--mipsel.ld225
-rw-r--r--monitor.c394
-rw-r--r--osdep.c94
-rw-r--r--osdep.h13
-rw-r--r--pc-bios/Makefile7
-rw-r--r--pc-bios/README1
-rw-r--r--pc-bios/bios.binbin131072 -> 131072 bytes
-rw-r--r--pc-bios/bios.diff26
-rw-r--r--pc-bios/linux_boot.S29
-rw-r--r--pc-bios/linux_boot.binbin512 -> 0 bytes
-rw-r--r--pc-bios/openbios-sparc32bin241940 -> 272948 bytes
-rw-r--r--pc-bios/openbios-sparc64bin0 -> 475784 bytes
-rw-r--r--pc-bios/ppc_rom.binbin524288 -> 524288 bytes
-rw-r--r--ppc-dis.c4
-rw-r--r--ppc.ld224
-rw-r--r--qemu-binfmt-conf.sh24
-rw-r--r--qemu-doc.texi879
-rw-r--r--qemu-img.c97
-rw-r--r--qemu-img.texi24
-rw-r--r--qemu-tech.texi89
-rw-r--r--readline.c72
-rw-r--r--s390-dis.c1711
-rw-r--r--sdl.c168
-rw-r--r--sh4-dis.c12
-rw-r--r--slirp/COPYRIGHT2
-rw-r--r--slirp/bootp.c32
-rw-r--r--slirp/cksum.c14
-rw-r--r--slirp/debug.c66
-rw-r--r--slirp/debug.h4
-rw-r--r--slirp/if.c60
-rw-r--r--slirp/if.h8
-rw-r--r--slirp/ip_icmp.c30
-rw-r--r--slirp/ip_input.c30
-rw-r--r--slirp/ip_output.c14
-rw-r--r--slirp/libslirp.h14
-rw-r--r--slirp/main.h4
-rw-r--r--slirp/mbuf.c32
-rw-r--r--slirp/mbuf.h6
-rw-r--r--slirp/misc.c172
-rw-r--r--slirp/misc.h4
-rw-r--r--slirp/sbuf.c32
-rw-r--r--slirp/sbuf.h4
-rw-r--r--slirp/slirp.c112
-rw-r--r--slirp/socket.c144
-rw-r--r--slirp/socket.h14
-rw-r--r--slirp/tcp_input.c166
-rw-r--r--slirp/tcp_output.c46
-rw-r--r--slirp/tcp_subr.c294
-rw-r--r--slirp/tcp_timer.c22
-rw-r--r--slirp/tftp.c131
-rw-r--r--slirp/tftp.h5
-rw-r--r--slirp/udp.c140
-rw-r--r--slirp/udp.h2
-rw-r--r--softmmu-semi.h67
-rw-r--r--softmmu_header.h38
-rw-r--r--softmmu_template.h34
-rw-r--r--sparc-dis.c50
-rw-r--r--sparc.ld3
-rw-r--r--tap-win32.c52
-rw-r--r--target-alpha/cpu.h400
-rw-r--r--target-alpha/exec.h92
-rw-r--r--target-alpha/helper.c454
-rw-r--r--target-alpha/op.c1103
-rw-r--r--target-alpha/op_helper.c1255
-rw-r--r--target-alpha/op_helper.h141
-rw-r--r--target-alpha/op_helper_mem.h40
-rw-r--r--target-alpha/op_mem.h125
-rw-r--r--target-alpha/op_template.h167
-rw-r--r--target-alpha/translate.c2119
-rw-r--r--target-arm/cpu.h106
-rw-r--r--target-arm/exec.h28
-rw-r--r--target-arm/helper.c566
-rw-r--r--target-arm/nwfpe/double_cpdo.c12
-rw-r--r--target-arm/nwfpe/extended_cpdo.c22
-rw-r--r--target-arm/nwfpe/fpa11.c60
-rw-r--r--target-arm/nwfpe/fpa11.h2
-rw-r--r--target-arm/nwfpe/fpa11_cpdo.c32
-rw-r--r--target-arm/nwfpe/fpa11_cpdt.c62
-rw-r--r--target-arm/nwfpe/fpa11_cprt.c48
-rw-r--r--target-arm/nwfpe/fpopcode.c22
-rw-r--r--target-arm/nwfpe/fpopcode.h18
-rw-r--r--target-arm/nwfpe/fpsr.h4
-rw-r--r--target-arm/nwfpe/single_cpdo.c10
-rw-r--r--target-arm/op.c33
-rw-r--r--target-arm/op_helper.c2
-rw-r--r--target-arm/op_iwmmxt.c707
-rw-r--r--target-arm/op_mem.h20
-rw-r--r--target-arm/op_template.h2
-rw-r--r--target-arm/translate.c1228
-rw-r--r--target-i386/cpu.h63
-rw-r--r--target-i386/exec.h40
-rw-r--r--target-i386/helper.c1042
-rw-r--r--target-i386/helper2.c189
-rw-r--r--target-i386/op.c121
-rw-r--r--target-i386/opreg_template.h2
-rw-r--r--target-i386/ops_sse.h6
-rw-r--r--target-i386/ops_template.h6
-rw-r--r--target-i386/ops_template_mem.h12
-rw-r--r--target-i386/svm.h358
-rw-r--r--target-i386/translate-copy.c78
-rw-r--r--target-i386/translate.c511
-rw-r--r--target-m68k/cpu.h105
-rw-r--r--target-m68k/exec.h16
-rw-r--r--target-m68k/helper.c192
-rw-r--r--target-m68k/op-hacks.h55
-rw-r--r--target-m68k/op.c602
-rw-r--r--target-m68k/op_helper.c159
-rw-r--r--target-m68k/op_mem.h46
-rw-r--r--target-m68k/qregs.def3
-rw-r--r--target-m68k/translate.c1224
-rw-r--r--target-mips/TODO14
-rw-r--r--target-mips/cpu.h355
-rw-r--r--target-mips/exec.h219
-rw-r--r--target-mips/fop_template.c127
-rw-r--r--target-mips/helper.c337
-rw-r--r--target-mips/mips-defs.h118
-rw-r--r--target-mips/op.c1866
-rw-r--r--target-mips/op_helper.c968
-rw-r--r--target-mips/op_helper_mem.c26
-rw-r--r--target-mips/op_mem.c28
-rw-r--r--target-mips/op_template.c43
-rw-r--r--target-mips/translate.c5126
-rw-r--r--target-mips/translate_init.c448
-rw-r--r--target-ppc/STATUS510
-rw-r--r--target-ppc/cpu.h1588
-rw-r--r--target-ppc/exec.h104
-rw-r--r--target-ppc/helper.c2973
-rw-r--r--target-ppc/mfrom_table.c79
-rw-r--r--target-ppc/mfrom_table_gen.c33
-rw-r--r--target-ppc/op.c2797
-rw-r--r--target-ppc/op_helper.c2397
-rw-r--r--target-ppc/op_helper.h470
-rw-r--r--target-ppc/op_helper_mem.h355
-rw-r--r--target-ppc/op_mem.h1046
-rw-r--r--target-ppc/op_template.h141
-rw-r--r--target-ppc/translate.c5443
-rw-r--r--target-ppc/translate_init.c6257
-rw-r--r--target-sh4/README.sh42
-rw-r--r--target-sh4/cpu.h14
-rw-r--r--target-sh4/exec.h12
-rw-r--r--target-sh4/helper.c6
-rw-r--r--target-sh4/op.c129
-rw-r--r--target-sh4/op_helper.c7
-rw-r--r--target-sh4/op_mem.c2
-rw-r--r--target-sh4/translate.c201
-rw-r--r--target-sparc/cpu.h121
-rw-r--r--target-sparc/exec.h42
-rw-r--r--target-sparc/fop_template.h2
-rw-r--r--target-sparc/helper.c538
-rw-r--r--target-sparc/op.c1196
-rw-r--r--target-sparc/op_helper.c1415
-rw-r--r--target-sparc/op_mem.h36
-rw-r--r--target-sparc/op_template.h2
-rw-r--r--target-sparc/translate.c3907
-rw-r--r--tests/Makefile3
-rw-r--r--tests/hello-arm.c2
-rw-r--r--tests/linux-test.c36
-rw-r--r--tests/qruncom.c30
-rw-r--r--tests/runcom.c10
-rw-r--r--tests/test-arm-iwmmxt.s49
-rw-r--r--tests/test-i386-code16.S10
-rw-r--r--tests/test-i386-muldiv.h16
-rw-r--r--tests/test-i386-vm86.S25
-rw-r--r--tests/test-i386.c124
-rw-r--r--tests/test_path.c2
-rwxr-xr-xtexi2pod.pl2
-rw-r--r--thunk.c20
-rw-r--r--thunk.h8
-rw-r--r--translate-all.c30
-rw-r--r--translate-op.c2
-rw-r--r--uboot_image.h160
-rw-r--r--usb-linux.c62
-rw-r--r--vl.c2450
-rw-r--r--vl.h604
-rw-r--r--vnc.c1077
-rw-r--r--vnchextile.h4
473 files changed, 107865 insertions, 22548 deletions
diff --git a/.cvsignore b/.cvsignore
index ae68e450c..2d6f37f35 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -9,8 +9,11 @@ i386-darwin-user
i386-linux-user
ppc-softmmu
ppc64-softmmu
+ppcemb-softmmu
ppc-darwin-user
ppc-linux-user
+ppc64-linux-user
+ppcemb-linux-user
qemu-doc.html
qemu-tech.html
qemu-doc.info
@@ -23,16 +26,26 @@ sparc-linux-user
qemu-img
sparc-softmmu
x86_64-softmmu
+x86_64-linux-user
sparc64-linux-user
sparc64-softmmu
mips-softmmu
mipsel-softmmu
mips-linux-user
mipsel-linux-user
+mips64-softmmu
+mips64el-softmmu
+mipsn32-linux-user
+mipsn32el-linux-user
+mips64-linux-user
+mips64el-linux-user
m68k-linux-user
+m68k-softmmu
.gdbinit
sh4-linux-user
sh4-softmmu
+alpha-linux-user
+alpha-softmmu
*.aux
*.cp
*.dvi
diff --git a/Changelog b/Changelog
index ea9ea7492..f61a58061 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,18 @@
+ - TFTP booting from host directory (Anthony Liguori, Erwan Velu)
+ - Tap device emulation for Solaris (Sittichai Palanisong)
+ - Monitor multiplexing to several I/O channels (Jason Wessel)
+ - ds1225y nvram support (Herve Poussineau)
+ - CPU model selection support (J. Mayer, Paul Brook, Herve Poussineau)
+ - Several Sparc fixes (Aurelien Jarno, Blue Swirl)
+ - MIPS 64-bit FPU support (Thiemo Seufer)
+ - Xscale PDA emulation (Andrzei Zaborowski)
+ - ColdFire system emulation (Paul Brook)
+ - Improved SH4 support (Magnus Damm)
+ - MIPS64 support (Aurelien Jarno, Thiemo Seufer)
+ - Preliminary Alpha guest support (J. Mayer)
+ - Read-only support for Parallels disk images (Alex Beregszaszi)
+ - SVM (x86 virtualization) support (Alexander Graf)
+
version 0.9.0:
- Support for relative paths in backing files for disk images
@@ -23,7 +38,7 @@ version 0.8.2:
- switch to OpenBios for SPARC targets (Blue Swirl)
- VNC server fixes
- MIPS FPU support (Marius Groeger)
- - Solaris/SPARC host support (Ben Taylor)
+ - Solaris/SPARC host support (Juergen Keil)
- PPC breakpoints and single stepping (Jason Wessel)
- USB updates (Paul Brook)
- UDP/TCP/telnet character devices (Jason Wessel)
@@ -42,7 +57,7 @@ version 0.8.1:
- PC speaker support (Joachim Henke)
- IDE LBA48 support (Jens Axboe)
- SSE3 support
- - Solaris port (Ben Taylor)
+ - Solaris port (Juergen Keil)
- Preliminary SH4 target (Samuel Tardieu)
- VNC server (Anthony Liguori)
- slirp fixes (Ed Swierk et al.)
@@ -72,7 +87,7 @@ version 0.8.0:
(Johannes Schindelin)
version 0.7.2:
-
+
- x86_64 fixes (Win2000 and Linux 2.6 boot in 32 bit)
- merge self modifying code handling in dirty ram page mecanism.
- MIPS fixes (Ralf Baechle)
@@ -121,7 +136,7 @@ version 0.6.1:
- Mac OS X port (Pierre d'Herbemont)
- Virtual console support
- Better monitor line edition
- - New block device layer
+ - New block device layer
- New 'qcow' growable disk image support with AES encryption and
transparent decompression
- VMware 3 and 4 read-only disk image support (untested)
@@ -187,7 +202,7 @@ version 0.5.5:
- 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)
@@ -214,7 +229,7 @@ version 0.5.3:
- added accurate CR0.MP/ME/TS emulation
- fixed DMA memory write access (Win95 boot floppy fix)
- graphical x86 linux loader
- - command line monitor
+ - command line monitor
- generic removable device support
- support of CD-ROM change
- multiple network interface support
@@ -252,7 +267,7 @@ version 0.5.2:
- eflags optimisation fix for string operations
version 0.5.1:
-
+
- float access fixes when using soft mmu
- PC emulation support on PowerPC
- A20 support
@@ -267,7 +282,7 @@ version 0.5.1:
- 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
@@ -305,7 +320,7 @@ version 0.4.2:
- SMP kernels can at least be booted
version 0.4.1:
-
+
- more accurate timer support in vl.
- more reliable NE2000 probe in vl.
- added 2.5.66 kernel in vl-test.
@@ -391,7 +406,7 @@ version 0.1.3:
- added bound, cmpxchg8b, cpuid instructions
- added 16 bit addressing support/override for string operations
- poll() fix
-
+
version 0.1.2:
- compile fixes
diff --git a/Makefile b/Makefile
index db76c89d9..5ed7eb5c4 100644
--- a/Makefile
+++ b/Makefile
@@ -8,13 +8,11 @@ include config-host.mak
BASE_CFLAGS=
BASE_LDFLAGS=
-BASE_CFLAGS += $(OS_CFLAGS)
-ifeq ($(ARCH),sparc)
-BASE_CFLAGS += -mcpu=ultrasparc
-endif
+BASE_CFLAGS += $(OS_CFLAGS) $(ARCH_CFLAGS)
+BASE_LDFLAGS += $(OS_LDFLAGS) $(ARCH_LDFLAGS)
+
CPPFLAGS += -I. -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
LIBS=
-TOOLS=qemu-img$(EXESUF)
ifdef CONFIG_STATIC
BASE_LDFLAGS += -static
endif
@@ -24,13 +22,7 @@ else
DOCS=
endif
-ifndef CONFIG_DARWIN
-ifndef CONFIG_WIN32
-ifndef CONFIG_SOLARIS
-LIBS+=-lrt
-endif
-endif
-endif
+LIBS+=$(AIOLIBS)
all: $(TOOLS) $(DOCS) recurse-all
@@ -39,7 +31,7 @@ subdir-%: dyngen$(EXESUF)
recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
-qemu-img$(EXESUF): qemu-img.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c
+qemu-img$(EXESUF): qemu-img.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c block-parallels.c
$(CC) -DQEMU_TOOL $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
dyngen$(EXESUF): dyngen.c
@@ -47,8 +39,8 @@ dyngen$(EXESUF): dyngen.c
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 *.pod *~ */*~
+ 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 cscope.* *.pod *~ */*~
$(MAKE) -C tests clean
for d in $(TARGET_DIRS); do \
$(MAKE) -C $$d $@ || exit 1 ; \
@@ -78,7 +70,7 @@ install: all $(if $(BUILD_DOCS),install-doc)
$(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
mkdir -p "$(DESTDIR)$(datadir)"
for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
- video.x openbios-sparc32 linux_boot.bin pxe-ne2k_pci.bin \
+ video.x openbios-sparc32 pxe-ne2k_pci.bin \
pxe-rtl8139.bin pxe-pcnet.bin; do \
$(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
done
@@ -96,7 +88,7 @@ endif
test speed test2: all
$(MAKE) -C tests $@
-TAGS:
+TAGS:
etags *.[ch] tests/*.[ch]
cscope:
@@ -140,21 +132,35 @@ tar:
# generate a binary distribution
tarbin:
- ( cd / ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \
+ ( cd / ; tar zcvf ~/qemu-$(VERSION)-$(ARCH).tar.gz \
$(bindir)/qemu \
$(bindir)/qemu-system-ppc \
+ $(bindir)/qemu-system-ppc64 \
+ $(bindir)/qemu-system-ppcemb \
$(bindir)/qemu-system-sparc \
$(bindir)/qemu-system-x86_64 \
$(bindir)/qemu-system-mips \
$(bindir)/qemu-system-mipsel \
+ $(bindir)/qemu-system-mips64 \
+ $(bindir)/qemu-system-mips64el \
$(bindir)/qemu-system-arm \
+ $(bindir)/qemu-system-m68k \
+ $(bindir)/qemu-system-sh4 \
$(bindir)/qemu-i386 \
$(bindir)/qemu-arm \
$(bindir)/qemu-armeb \
$(bindir)/qemu-sparc \
$(bindir)/qemu-ppc \
+ $(bindir)/qemu-ppc64 \
$(bindir)/qemu-mips \
$(bindir)/qemu-mipsel \
+ $(bindir)/qemu-mipsn32 \
+ $(bindir)/qemu-mipsn32el \
+ $(bindir)/qemu-mips64 \
+ $(bindir)/qemu-mips64el \
+ $(bindir)/qemu-alpha \
+ $(bindir)/qemu-m68k \
+ $(bindir)/qemu-sh4 \
$(bindir)/qemu-img \
$(datadir)/bios.bin \
$(datadir)/vgabios.bin \
@@ -162,7 +168,6 @@ tarbin:
$(datadir)/ppc_rom.bin \
$(datadir)/video.x \
$(datadir)/openbios-sparc32 \
- $(datadir)/linux_boot.bin \
$(datadir)/pxe-ne2k_pci.bin \
$(datadir)/pxe-rtl8139.bin \
$(datadir)/pxe-pcnet.bin \
diff --git a/Makefile.target b/Makefile.target
index dc9a96575..9b0459ec1 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -4,9 +4,18 @@ TARGET_BASE_ARCH:=$(TARGET_ARCH)
ifeq ($(TARGET_ARCH), x86_64)
TARGET_BASE_ARCH:=i386
endif
+ifeq ($(TARGET_ARCH), mipsn32)
+TARGET_BASE_ARCH:=mips
+endif
+ifeq ($(TARGET_ARCH), mips64)
+TARGET_BASE_ARCH:=mips
+endif
ifeq ($(TARGET_ARCH), ppc64)
TARGET_BASE_ARCH:=ppc
endif
+ifeq ($(TARGET_ARCH), ppcemb)
+TARGET_BASE_ARCH:=ppc
+endif
ifeq ($(TARGET_ARCH), sparc64)
TARGET_BASE_ARCH:=sparc
endif
@@ -44,6 +53,16 @@ ifeq ($(TARGET_ARCH),mips)
TARGET_ARCH2=mipsel
endif
endif
+ifeq ($(TARGET_ARCH),mipsn32)
+ ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
+ TARGET_ARCH2=mipsn32el
+ endif
+endif
+ifeq ($(TARGET_ARCH),mips64)
+ ifneq ($(TARGET_WORDS_BIGENDIAN),yes)
+ TARGET_ARCH2=mips64el
+ endif
+endif
QEMU_USER=qemu-$(TARGET_ARCH2)
# system emulator name
ifdef CONFIG_SOFTMMU
@@ -70,16 +89,27 @@ BASE_LDFLAGS+=-static
endif
# We require -O2 to avoid the stack setup prologue in EXIT_TB
-OP_CFLAGS = -Wall -O2 -g -fno-strict-aliasing
+OP_CFLAGS := -Wall -O2 -g -fno-strict-aliasing
+
+# cc-option
+# Usage: OP_CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0)
+
+cc-option = $(shell if $(CC) $(OP_CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
+ > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
+
+OP_CFLAGS+=$(call cc-option, -fno-reorder-blocks, "")
+OP_CFLAGS+=$(call cc-option, -fno-gcse, "")
+OP_CFLAGS+=$(call cc-option, -fno-tree-ch, "")
+OP_CFLAGS+=$(call cc-option, -fno-optimize-sibling-calls, "")
+OP_CFLAGS+=$(call cc-option, -fno-crossjumping, "")
+OP_CFLAGS+=$(call cc-option, -fno-align-labels, "")
+OP_CFLAGS+=$(call cc-option, -fno-align-jumps, "")
+OP_CFLAGS+=$(call cc-option, -fno-align-functions, $(call cc-option, -malign-functions=0, ""))
+OP_CFLAGS+=$(call cc-option, -fno-section-anchors, "")
ifeq ($(ARCH),i386)
HELPER_CFLAGS+=-fomit-frame-pointer
OP_CFLAGS+=-mpreferred-stack-boundary=2 -fomit-frame-pointer
-ifeq ($(HAVE_GCC3_OPTIONS),yes)
-OP_CFLAGS+= -falign-functions=0 -fno-gcse
-else
-OP_CFLAGS+= -malign-functions=0
-endif
ifdef TARGET_GPROF
USE_I386_LD=y
endif
@@ -114,25 +144,25 @@ BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
endif
ifeq ($(ARCH),sparc)
-ifeq ($(CONFIG_SOLARIS),yes)
-BASE_CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3
-BASE_LDFLAGS+=-m32
-OP_CFLAGS+=-fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0
-else
-BASE_CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
-BASE_LDFLAGS+=-m32
-OP_CFLAGS+=-fno-delayed-branch -ffixed-i0
-HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
-# -static is used to avoid g1/g3 usage by the dynamic linker
-BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
-endif
+ BASE_CFLAGS+=-ffixed-g2 -ffixed-g3
+ OP_CFLAGS+=-fno-delayed-branch -ffixed-i0
+ ifeq ($(CONFIG_SOLARIS),yes)
+ OP_CFLAGS+=-fno-omit-frame-pointer
+ else
+ BASE_CFLAGS+=-ffixed-g1 -ffixed-g6
+ HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
+ # -static is used to avoid g1/g3 usage by the dynamic linker
+ BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
+ endif
endif
ifeq ($(ARCH),sparc64)
-BASE_CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
-BASE_LDFLAGS+=-m64
-BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
-OP_CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7 -fno-delayed-branch -ffixed-i0
+ BASE_CFLAGS+=-ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
+ OP_CFLAGS+=-mcpu=ultrasparc -m64 -fno-delayed-branch -ffixed-i0
+ ifneq ($(CONFIG_SOLARIS),yes)
+ BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+ OP_CFLAGS+=-ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
+ endif
endif
ifeq ($(ARCH),alpha)
@@ -160,12 +190,21 @@ BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
endif
ifeq ($(ARCH),mips)
+OP_CFLAGS+=-mabi=32 -G0 -fno-PIC -mno-abicalls -fomit-frame-pointer -fno-delayed-branch -Wa,-O0
+ifeq ($(WORDS_BIGENDIAN),yes)
BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+else
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH)el.ld
+endif
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
+ifeq ($(ARCH),mips64)
+OP_CFLAGS+=-mabi=n32 -G0 -fno-PIC -mno-abicalls -fomit-frame-pointer -fno-delayed-branch -Wa,-O0
+ifeq ($(WORDS_BIGENDIAN),yes)
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+else
+BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH)el.ld
+endif
endif
ifeq ($(CONFIG_DARWIN),yes)
@@ -177,7 +216,10 @@ ifdef CONFIG_DARWIN_USER
BASE_LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e000000
endif
-OP_CFLAGS+=$(OS_CFLAGS)
+BASE_CFLAGS+=$(OS_CFLAGS) $(ARCH_CFLAGS)
+BASE_LDFLAGS+=$(OS_LDFLAGS) $(ARCH_LDFLAGS)
+OP_CFLAGS+=$(OS_CFLAGS) $(ARCH_CFLAGS)
+OP_LDFLAGS+=$(OS_LDFLAGS) $(ARCH_LDFLAGS)
#########################################################
@@ -191,6 +233,12 @@ LIBS+=-lwinmm -lws2_32 -liphlpapi
endif
ifdef CONFIG_SOLARIS
LIBS+=-lsocket -lnsl -lresolv
+ifdef NEEDS_LIBSUNMATH
+LIBS+=-lsunmath
+LDFLAGS+=-L/opt/SUNWspro/prod/lib -R/opt/SUNWspro/prod/lib
+OP_CFLAGS+=-I/opt/SUNWspro/prod/include/cc
+BASE_CFLAGS+=-I/opt/SUNWspro/prod/include/cc
+endif
endif
# profiling code
@@ -202,6 +250,7 @@ endif
ifdef CONFIG_LINUX_USER
OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \
elfload.o linuxload.o
+LIBS+= $(AIOLIBS)
ifdef TARGET_HAS_BFLT
OBJS+= flatload.o
endif
@@ -228,7 +277,7 @@ OBJS+= libqemu.a
# cpu emulator library
LIBOBJS=exec.o kqemu.o translate-op.o translate-all.o cpu-exec.o\
- translate.o op.o
+ translate.o op.o host-utils.o
ifdef CONFIG_SOFTFLOAT
LIBOBJS+=fpu/softfloat.o
else
@@ -251,7 +300,7 @@ ifeq ($(TARGET_BASE_ARCH), ppc)
LIBOBJS+= op_helper.o helper.o
endif
-ifeq ($(TARGET_ARCH), mips)
+ifeq ($(TARGET_BASE_ARCH), mips)
LIBOBJS+= op_helper.o helper.o
endif
@@ -268,11 +317,15 @@ LIBOBJS+= op_helper.o helper.o
endif
ifeq ($(TARGET_BASE_ARCH), m68k)
-LIBOBJS+= helper.o
+LIBOBJS+= op_helper.o helper.o
+endif
+
+ifeq ($(TARGET_BASE_ARCH), alpha)
+LIBOBJS+= op_helper.o helper.o alpha_palcode.o
endif
# NOTE: the disassembler code is only needed for debugging
-LIBOBJS+=disas.o
+LIBOBJS+=disas.o
ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
USE_I386_DIS=y
endif
@@ -288,7 +341,7 @@ endif
ifeq ($(findstring ppc, $(TARGET_BASE_ARCH) $(ARCH)),ppc)
LIBOBJS+=ppc-dis.o
endif
-ifeq ($(findstring mips, $(TARGET_ARCH) $(ARCH)),mips)
+ifeq ($(findstring mips, $(TARGET_BASE_ARCH) $(ARCH)),mips)
LIBOBJS+=mips-dis.o
endif
ifeq ($(findstring sparc, $(TARGET_BASE_ARCH) $(ARCH)),sparc)
@@ -303,6 +356,9 @@ endif
ifeq ($(findstring sh4, $(TARGET_ARCH) $(ARCH)),sh4)
LIBOBJS+=sh4-dis.o
endif
+ifeq ($(findstring s390, $(TARGET_ARCH) $(ARCH)),s390)
+LIBOBJS+=s390-dis.o
+endif
ifdef CONFIG_GDBSTUB
OBJS+=gdbstub.o
@@ -322,13 +378,14 @@ endif
VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o loader.o isa_mmio.o
VL_OBJS+=cutils.o
VL_OBJS+=block.o block-raw.o
-VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o
+VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o block-parallels.o
+VL_OBJS+=irq.o
ifdef CONFIG_WIN32
VL_OBJS+=tap-win32.o
endif
SOUND_HW = sb16.o es1370.o
-AUDIODRV = audio.o noaudio.o wavaudio.o
+AUDIODRV = audio.o noaudio.o wavaudio.o mixeng.o
ifdef CONFIG_SDL
AUDIODRV += sdlaudio.o
endif
@@ -356,64 +413,90 @@ SOUND_HW += fmopl.o adlib.o
endif
AUDIODRV+= wavcapture.o
+ifdef CONFIG_VNC_TLS
+CPPFLAGS += $(CONFIG_VNC_TLS_CFLAGS)
+LIBS += $(CONFIG_VNC_TLS_LIBS)
+endif
+
+VL_OBJS += i2c.o smbus.o
+
# SCSI layer
VL_OBJS+= scsi-disk.o cdrom.o lsi53c895a.o
# USB layer
VL_OBJS+= usb.o usb-hub.o usb-linux.o usb-hid.o usb-ohci.o usb-msd.o
+VL_OBJS+= usb-wacom.o
+
+# EEPROM emulation
+VL_OBJS += eeprom93xx.o
# PCI network cards
-VL_OBJS+= ne2000.o rtl8139.o pcnet.o
+VL_OBJS += eepro100.o
+VL_OBJS += ne2000.o
+VL_OBJS += pcnet.o
+VL_OBJS += rtl8139.o
ifeq ($(TARGET_BASE_ARCH), i386)
# Hardware support
VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pcspk.o pc.o
-VL_OBJS+= cirrus_vga.o mixeng.o apic.o parallel.o acpi.o piix_pci.o
-VL_OBJS+= usb-uhci.o smbus_eeprom.o
-CPPFLAGS += -DHAS_AUDIO
+VL_OBJS+= cirrus_vga.o apic.o parallel.o acpi.o piix_pci.o
+VL_OBJS+= usb-uhci.o smbus_eeprom.o vmmouse.o vmport.o vmware_vga.o
+CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
endif
ifeq ($(TARGET_BASE_ARCH), ppc)
VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
-VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
-VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
-VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o
+VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o pflash_cfi02.o
+VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o
+VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o ppc405_uc.o ppc405_boards.o
+CPPFLAGS += -DHAS_AUDIO -DHAS_AUDIO_CHOICE
+endif
+ifeq ($(TARGET_BASE_ARCH), mips)
+VL_OBJS+= mips_r4k.o mips_malta.o mips_pica61.o
+VL_OBJS+= mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o
+VL_OBJS+= jazz_led.o
+VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o ds1225y.o
+VL_OBJS+= piix_pci.o smbus_eeprom.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
CPPFLAGS += -DHAS_AUDIO
endif
-ifeq ($(TARGET_ARCH), mips)
-VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o
-VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o
-VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
-DEFINES += -DHAS_AUDIO
-endif
ifeq ($(TARGET_BASE_ARCH), sparc)
ifeq ($(TARGET_ARCH), sparc64)
VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o
VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o
-VL_OBJS+= cirrus_vga.o parallel.o
+VL_OBJS+= cirrus_vga.o parallel.o ptimer.o
else
VL_OBJS+= sun4m.o tcx.o pcnet.o iommu.o m48t59.o slavio_intctl.o
VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o sparc32_dma.o
-VL_OBJS+= cs4231.o
+VL_OBJS+= cs4231.o ptimer.o
endif
endif
ifeq ($(TARGET_BASE_ARCH), arm)
VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o
-VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl190.o
-VL_OBJS+= versatile_pci.o
+VL_OBJS+= arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
+VL_OBJS+= versatile_pci.o sd.o ptimer.o
VL_OBJS+= arm_gic.o realview.o arm_sysctl.o
VL_OBJS+= arm-semi.o
+VL_OBJS+= pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
+VL_OBJS+= pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o max111x.o max7310.o
+VL_OBJS+= spitz.o ads7846.o ide.o serial.o nand.o $(AUDIODRV) wm8750.o
+VL_OBJS+= omap.o omap_lcdc.o omap1_clk.o omap_mmc.o palm.o ecc.o
+CPPFLAGS += -DHAS_AUDIO
endif
ifeq ($(TARGET_BASE_ARCH), sh4)
-VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
+VL_OBJS+= shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
+VL_OBJS+= sh_timer.o ptimer.o sh_serial.o
+endif
+ifeq ($(TARGET_BASE_ARCH), m68k)
+VL_OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
+VL_OBJS+= m68k-semi.o
endif
ifdef CONFIG_GDBSTUB
-VL_OBJS+=gdbstub.o
+VL_OBJS+=gdbstub.o
endif
ifdef CONFIG_SDL
VL_OBJS+=sdl.o x_keymap.o
endif
-VL_OBJS+=vnc.o
+VL_OBJS+=vnc.o d3des.o
ifdef CONFIG_COCOA
VL_OBJS+=cocoa.o
COCOA_LIBS=-F/System/Library/Frameworks -framework Cocoa -framework IOKit
@@ -429,18 +512,19 @@ tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o
VL_OBJS+=$(addprefix slirp/, $(SLIRP_OBJS))
endif
-VL_LDFLAGS=
+VL_LDFLAGS=$(VL_OS_LDFLAGS)
+VL_LIBS=$(AIOLIBS)
# 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
+VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386-vl.ld
endif
ifndef CONFIG_DARWIN
ifndef CONFIG_WIN32
ifndef CONFIG_SOLARIS
-VL_LIBS=-lutil -lrt
+VL_LIBS+=-lutil
endif
endif
endif
@@ -454,8 +538,10 @@ VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
endif
ifeq ($(ARCH),sparc64)
-VL_LDFLAGS+=-m64
-VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld
+ VL_LDFLAGS+=-m64
+ ifneq ($(CONFIG_SOLARIS),yes)
+ VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
+ endif
endif
ifdef CONFIG_WIN32
@@ -463,7 +549,7 @@ SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole
endif
$(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
- $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
+ $(CC) $(VL_LDFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
cocoa.o: cocoa.m
$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
@@ -471,7 +557,7 @@ cocoa.o: cocoa.m
sdl.o: sdl.c keymaps.c sdl_keysym.h
$(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
-vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h
+vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h d3des.c d3des.h
$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
sdlaudio.o: sdlaudio.c
@@ -483,7 +569,7 @@ depend: $(SRCS)
vldepend: $(VL_OBJS:.o=.c)
$(CC) -MM $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $^ 1>.depend
-# libqemu
+# libqemu
libqemu.a: $(LIBOBJS)
rm -f $@
@@ -526,6 +612,10 @@ cpu-exec.o: cpu-exec.c
signal.o: signal.c
$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
+vga.o: pixel_ops.h
+
+tcx.o: pixel_ops.h
+
ifeq ($(TARGET_BASE_ARCH), i386)
op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h ops_sse.h
endif
@@ -536,19 +626,23 @@ pl110.o: pl110_template.h
endif
ifeq ($(TARGET_BASE_ARCH), sparc)
-op.o: op.c op_template.h op_mem.h fop_template.h fbranch_template.h
-magic_load.o: elf_op.h
+helper.o: cpu.h exec-all.h
+op.o: op.c op_template.h op_mem.h fop_template.h fbranch_template.h exec.h cpu.h
+op_helper.o: exec.h softmmu_template.h cpu.h
+translate.o: cpu.h exec-all.h disas.h
endif
ifeq ($(TARGET_BASE_ARCH), ppc)
-op.o: op.c op_template.h op_mem.h
-op_helper.o: op_helper_mem.h
+op.o: op.c op_template.h op_mem.h op_helper.h
+op_helper.o: op_helper.c mfrom_table.c op_helper_mem.h op_helper.h
translate.o: translate.c translate_init.c
endif
-ifeq ($(TARGET_ARCH), mips)
-op.o: op.c op_template.c fop_template.c op_mem.c
-op_helper.o: op_helper_mem.c
+ifeq ($(TARGET_BASE_ARCH), mips)
+helper.o: cpu.h exec-all.h
+op.o: op_template.c fop_template.c op_mem.c exec.h cpu.h
+op_helper.o: op_helper_mem.c exec.h softmmu_template.h cpu.h
+translate.o: translate_init.c exec-all.h disas.h
endif
loader.o: loader.c elf_ops.h
@@ -563,6 +657,11 @@ sh7750_regnames.o: sh7750_regnames.c sh7750_regnames.h sh7750_regs.h
tc58128.o: tc58128.c
endif
+ifeq ($(TARGET_BASE_ARCH), alpha)
+op.o: op.c op_template.h op_mem.h
+op_helper.o: op_helper_mem.h
+endif
+
$(OBJS) $(LIBOBJS) $(VL_OBJS): config.h ../config-host.h
%.o: %.c
@@ -574,7 +673,7 @@ $(OBJS) $(LIBOBJS) $(VL_OBJS): config.h ../config-host.h
clean:
rm -f *.o *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o fpu/*.o
-install: all
+install: all
ifneq ($(PROGS),)
$(INSTALL) -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)"
endif
diff --git a/TODO b/TODO
index 516ea87bf..178a071bf 100644
--- a/TODO
+++ b/TODO
@@ -16,7 +16,7 @@ short term:
- do not resize vga if invalid size.
- avoid looping if only exceptions
- TLB code protection support for PPC
-- see openMosix Doc
+- see openMosix Doc
- disable SMC handling for ARM/SPARC/PPC (not finished)
- see undefined flags for BTx insn
- user/kernel PUSHL/POPL in helper.c
diff --git a/a.out.h b/a.out.h
index 1f978c1c0..2d35ebfd8 100644
--- a/a.out.h
+++ b/a.out.h
@@ -25,9 +25,9 @@ extern "C" {
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 */
+ host_ulong f_timdat; /* time & date stamp */
+ host_ulong f_symptr; /* file pointer to symtab */
+ host_ulong f_nsyms; /* number of symtab entries */
short f_opthdr; /* sizeof(optional hdr) */
short f_flags; /* flags */
};
@@ -72,12 +72,12 @@ 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=
+ host_ulong tsize; /* text size in bytes, padded to FW bdry*/
+ host_ulong dsize; /* initialized data " " */
+ host_ulong bsize; /* uninitialized data " " */
+ host_ulong entry; /* entry pt. */
+ host_ulong text_start; /* base of text used for this file */
+ host_ulong data_start; /* base of data used for this file=
*/
}
AOUTHDR;
@@ -103,16 +103,16 @@ AOUTHDR;
struct external_scnhdr {
char s_name[8]; /* section name */
- unsigned long s_paddr; /* physical address, offset
+ host_ulong 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 */
+ host_ulong s_vaddr; /* virtual address */
+ host_ulong s_size; /* section size */
+ host_ulong s_scnptr; /* file ptr to raw data for section */
+ host_ulong s_relptr; /* file ptr to relocation */
+ host_ulong 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 */
+ host_ulong s_flags; /* flags */
};
#define SCNHDR struct external_scnhdr
@@ -136,8 +136,8 @@ struct external_scnhdr {
*/
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 */
+ host_ulong l_symndx; /* function name symbol index, iff l_lnno 0 */
+ host_ulong l_paddr; /* (physical) address of line number */
} l_addr;
unsigned short l_lnno; /* line number */
};
@@ -156,11 +156,11 @@ struct __attribute__((packed)) external_syment
union {
char e_name[E_SYMNMLEN];
struct {
- unsigned long e_zeroes;
- unsigned long e_offset;
+ host_ulong e_zeroes;
+ host_ulong e_offset;
} e;
} e;
- unsigned long e_value;
+ host_ulong e_value;
unsigned short e_scnum;
unsigned short e_type;
char e_sclass[1];
@@ -174,18 +174,18 @@ struct __attribute__((packed)) external_syment
union external_auxent {
struct {
- unsigned long x_tagndx; /* str, un, or enum tag indx */
+ host_ulong 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 */
+ host_ulong 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 */
+ host_ulong x_lnnoptr;/* ptr to fcn line # */
+ host_ulong x_endndx; /* entry ndx past block end */
} x_fcn;
struct { /* if ISARY, up to 4 dimen. */
char x_dimen[E_DIMNUM][2];
@@ -197,22 +197,22 @@ union external_auxent {
union {
char x_fname[E_FILNMLEN];
struct {
- unsigned long x_zeroes;
- unsigned long x_offset;
+ host_ulong x_zeroes;
+ host_ulong x_offset;
} x_n;
} x_file;
struct {
- unsigned long x_scnlen; /* section length */
+ host_ulong x_scnlen; /* section length */
unsigned short x_nreloc; /* # relocation entries */
unsigned short x_nlinno; /* # line numbers */
- unsigned long x_checksum; /* section COMDAT checksum */
+ host_ulong 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 */
+ host_ulong 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)) */
@@ -344,7 +344,7 @@ struct external_PE_filehdr
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 */
+ host_ulong 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 */
@@ -352,9 +352,9 @@ struct external_PE_filehdr
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 */
+ host_ulong f_timdat; /* time & date stamp */
+ host_ulong f_symptr; /* file pointer to symtab */
+ host_ulong f_nsyms; /* number of symtab entries */
unsigned short f_opthdr; /* sizeof(optional hdr) */
unsigned short f_flags; /* flags */
};
@@ -370,17 +370,17 @@ 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 */
+ host_ulong tsize; /* text size in bytes, padded to FW bdry*/
+ host_ulong dsize; /* initialized data " " */
+ host_ulong bsize; /* uninitialized data " " */
+ host_ulong entry; /* entry pt. */
+ host_ulong text_start; /* base of text used for this file */
+ host_ulong 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;
+ host_ulong ImageBase;
+ host_ulong SectionAlignment;
+ host_ulong FileAlignment;
unsigned short MajorOperatingSystemVersion;
unsigned short MinorOperatingSystemVersion;
unsigned short MajorImageVersion;
@@ -388,17 +388,17 @@ typedef struct
unsigned short MajorSubsystemVersion;
unsigned short MinorSubsystemVersion;
char Reserved1[4];
- unsigned long SizeOfImage;
- unsigned long SizeOfHeaders;
- unsigned long CheckSum;
+ host_ulong SizeOfImage;
+ host_ulong SizeOfHeaders;
+ host_ulong 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;
+ host_ulong SizeOfStackReserve;
+ host_ulong SizeOfStackCommit;
+ host_ulong SizeOfHeapReserve;
+ host_ulong SizeOfHeapCommit;
+ host_ulong LoaderFlags;
+ host_ulong NumberOfRvaAndSizes;
/* IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; */
char DataDirectory[16][2][4]; /* 16 entries, 2 elements/entry, 4 chars */
diff --git a/aes.c b/aes.c
index cd4484ff9..40ed109d3 100644
--- a/aes.c
+++ b/aes.c
@@ -1,5 +1,5 @@
/**
- *
+ *
* aes.c - integrated in QEMU by Fabrice Bellard from the OpenSSL project.
*/
/*
@@ -1267,7 +1267,7 @@ void AES_decrypt(const unsigned char *in, unsigned char *out,
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
const unsigned long length, const AES_KEY *key,
- unsigned char *ivec, const int enc)
+ unsigned char *ivec, const int enc)
{
unsigned long n;
@@ -1294,7 +1294,7 @@ void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
AES_encrypt(tmp, tmp, key);
memcpy(out, tmp, AES_BLOCK_SIZE);
memcpy(ivec, tmp, AES_BLOCK_SIZE);
- }
+ }
} else {
while (len >= AES_BLOCK_SIZE) {
memcpy(tmp, in, AES_BLOCK_SIZE);
@@ -1312,6 +1312,6 @@ void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
for(n=0; n < len; ++n)
out[n] = tmp[n] ^ ivec[n];
memcpy(ivec, tmp, AES_BLOCK_SIZE);
- }
+ }
}
}
diff --git a/alpha-dis.c b/alpha-dis.c
index 81a55e9c0..c6af1aa75 100644
--- a/alpha-dis.c
+++ b/alpha-dis.c
@@ -374,7 +374,7 @@ const struct alpha_operand alpha_operands[] =
/* The signed "23-bit" aligned displacement of Branch format insns */
#define BDISP (MDISP + 1)
- { 21, 0, BFD_RELOC_23_PCREL_S2,
+ { 21, 0, BFD_RELOC_23_PCREL_S2,
AXP_OPERAND_RELATIVE, insert_bdisp, extract_bdisp },
/* The 26-bit PALcode function */
diff --git a/arm-dis.c b/arm-dis.c
index 1e027efc7..11f580b2f 100644
--- a/arm-dis.c
+++ b/arm-dis.c
@@ -4,17 +4,17 @@
Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
Modification by James G. Smith (jsmith@cygnus.co.uk)
-This file is part of libopcodes.
+This file is part of libopcodes.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option)
-any later version.
+any later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-more details.
+more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
@@ -34,7 +34,7 @@ struct thumb_opcode
};
/* format of the assembler string :
-
+
%% %
%<bitfield>d print the bitfield in decimal
%<bitfield>x print the bitfield in hex
@@ -104,7 +104,7 @@ static struct arm_opcode arm_opcodes[] =
{0x0c400000, 0x0ff00fff, "mar%c\tacc0, %12-15r, %16-19r"},
{0x0c500000, 0x0ff00fff, "mra%c\t%12-15r, %16-19r, acc0"},
{0xf450f000, 0xfc70f000, "pld\t%a"},
-
+
/* V5 Instructions. */
{0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"},
{0xfa000000, 0xfe000000, "blx\t%B"},
@@ -116,7 +116,7 @@ static struct arm_opcode arm_opcodes[] =
{0xfe000010, 0xff100010, "mcr2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
{0xfe100010, 0xff100010, "mrc2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
- /* V5E "El Segundo" Instructions. */
+ /* V5E "El Segundo" Instructions. */
{0x000000d0, 0x0e1000f0, "ldr%cd\t%12-15r, %s"},
{0x000000f0, 0x0e1000f0, "str%cd\t%12-15r, %s"},
{0x01000080, 0x0ff000f0, "smlabb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
@@ -303,7 +303,7 @@ static struct arm_opcode arm_opcodes[] =
{0x0d100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
{0x0c100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
{0x0d500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
- {0x0c500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
+ {0x0c500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
{0x0d100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
{0x0c100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
{0x0d500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
@@ -571,7 +571,7 @@ static boolean force_thumb = false;
static char * arm_fp_const[] =
{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
-static char * arm_shift[] =
+static char * arm_shift[] =
{"lsl", "lsr", "asr", "ror"};
/* Forward declarations. */
@@ -621,14 +621,14 @@ arm_decode_shift (given, func, stream)
void * stream;
{
func (stream, "%s", arm_regnames[given & 0xf]);
-
+
if ((given & 0xff0) != 0)
{
if ((given & 0x10) == 0)
{
int amount = (given & 0xf80) >> 7;
int shift = (given & 0x60) >> 5;
-
+
if (amount == 0)
{
if (shift == 3)
@@ -636,10 +636,10 @@ arm_decode_shift (given, func, stream)
func (stream, ", rrx");
return;
}
-
+
amount = 32;
}
-
+
func (stream, ", %s #%d", arm_shift[shift], amount);
}
else
@@ -666,7 +666,7 @@ print_insn_arm1 (pc, info, given)
if ((given & insn->mask) == insn->value)
{
char * c;
-
+
for (c = insn->assembler; *c; c++)
{
if (*c == '%')
@@ -682,14 +682,14 @@ print_insn_arm1 (pc, info, given)
&& ((given & 0x02000000) == 0))
{
int offset = given & 0xfff;
-
+
func (stream, "[pc");
-
+
if (given & 0x01000000)
{
if ((given & 0x00800000) == 0)
offset = - offset;
-
+
/* Pre-indexed. */
func (stream, ", #%d]", offset);
@@ -710,13 +710,13 @@ print_insn_arm1 (pc, info, given)
/* ie ignore the offset. */
offset = pc + 8;
}
-
+
func (stream, "\t; ");
info->print_address_func (offset, info);
}
else
{
- func (stream, "[%s",
+ func (stream, "[%s",
arm_regnames[(given >> 16) & 0xf]);
if ((given & 0x01000000) != 0)
{
@@ -736,7 +736,7 @@ print_insn_arm1 (pc, info, given)
arm_decode_shift (given, func, stream);
}
- func (stream, "]%s",
+ func (stream, "]%s",
((given & 0x00200000) != 0) ? "!" : "");
}
else
@@ -748,13 +748,13 @@ print_insn_arm1 (pc, info, given)
func (stream, "], %s#%d",
(((given & 0x00800000) == 0)
? "-" : ""), offset);
- else
+ else
func (stream, "]");
}
else
{
func (stream, "], %s",
- (((given & 0x00800000) == 0)
+ (((given & 0x00800000) == 0)
? "-" : ""));
arm_decode_shift (given, func, stream);
}
@@ -767,18 +767,18 @@ print_insn_arm1 (pc, info, given)
{
/* PC relative with immediate offset. */
int offset = ((given & 0xf00) >> 4) | (given & 0xf);
-
+
if ((given & 0x00800000) == 0)
offset = -offset;
-
+
func (stream, "[pc, #%d]\t; ", offset);
-
+
(*info->print_address_func)
(offset + pc + 8, info);
}
else
{
- func (stream, "[%s",
+ func (stream, "[%s",
arm_regnames[(given >> 16) & 0xf]);
if ((given & 0x01000000) != 0)
{
@@ -801,7 +801,7 @@ print_insn_arm1 (pc, info, given)
arm_regnames[given & 0xf]);
}
- func (stream, "]%s",
+ func (stream, "]%s",
((given & 0x00200000) != 0) ? "!" : "");
}
else
@@ -815,7 +815,7 @@ print_insn_arm1 (pc, info, given)
func (stream, "], %s#%d",
(((given & 0x00800000) == 0)
? "-" : ""), offset);
- else
+ else
func (stream, "]");
}
else
@@ -829,7 +829,7 @@ print_insn_arm1 (pc, info, given)
}
}
break;
-
+
case 'b':
(*info->print_address_func)
(BDISP (given) * 4 + pc + 8, info);
@@ -911,7 +911,7 @@ print_insn_arm1 (pc, info, given)
{
bfd_vma address;
bfd_vma offset = 0;
-
+
if (given & 0x00800000)
/* Is signed, hi bits should be ones. */
offset = (-1) ^ 0x00ffffff;
@@ -920,7 +920,7 @@ print_insn_arm1 (pc, info, given)
offset += given & 0x00ffffff;
offset <<= 2;
address = offset + pc + 8;
-
+
if (given & 0x01000000)
/* H bit allows addressing to 2-byte boundaries. */
address += 2;
@@ -976,7 +976,7 @@ print_insn_arm1 (pc, info, given)
func (stream, "3");
}
break;
-
+
case 'P':
switch (given & 0x00080080)
{
@@ -1028,7 +1028,7 @@ print_insn_arm1 (pc, info, given)
}
break;
- case '0': case '1': case '2': case '3': case '4':
+ case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
int bitstart = *c++ - '0';
@@ -1040,44 +1040,44 @@ print_insn_arm1 (pc, info, given)
{
case '-':
c++;
-
+
while (*c >= '0' && *c <= '9')
bitend = (bitend * 10) + *c++ - '0';
-
+
if (!bitend)
abort ();
-
+
switch (*c)
{
case 'r':
{
long reg;
-
+
reg = given >> bitstart;
reg &= (2 << (bitend - bitstart)) - 1;
-
+
func (stream, "%s", arm_regnames[reg]);
}
break;
case 'd':
{
long reg;
-
+
reg = given >> bitstart;
reg &= (2 << (bitend - bitstart)) - 1;
-
+
func (stream, "%d", reg);
}
break;
case 'x':
{
long reg;
-
+
reg = given >> bitstart;
reg &= (2 << (bitend - bitstart)) - 1;
-
+
func (stream, "0x%08x", reg);
-
+
/* Some SWI instructions have special
meanings. */
if ((given & 0x0fffffff) == 0x0FF00000)
@@ -1089,20 +1089,20 @@ print_insn_arm1 (pc, info, given)
case 'X':
{
long reg;
-
+
reg = given >> bitstart;
reg &= (2 << (bitend - bitstart)) - 1;
-
+
func (stream, "%01x", reg & 0xf);
}
break;
case 'f':
{
long reg;
-
+
reg = given >> bitstart;
reg &= (2 << (bitend - bitstart)) - 1;
-
+
if (reg > 7)
func (stream, "#%s",
arm_fp_const[reg & 7]);
@@ -1163,7 +1163,7 @@ print_insn_arm1 (pc, info, given)
}
break;
-
+
default:
abort ();
}
@@ -1252,7 +1252,7 @@ print_insn_thumb (pc, info, given)
if (!*c) /* Check for empty (not NULL) assembler string. */
{
long offset;
-
+
info->bytes_per_chunk = 4;
info->bytes_per_line = 4;
@@ -1274,16 +1274,16 @@ print_insn_thumb (pc, info, given)
{
info->bytes_per_chunk = 2;
info->bytes_per_line = 4;
-
+
given &= 0xffff;
-
+
for (; *c; c++)
{
if (*c == '%')
{
int domaskpc = 0;
int domasklr = 0;
-
+
switch (*++c)
{
case '%':
@@ -1293,11 +1293,11 @@ print_insn_thumb (pc, info, given)
case 'S':
{
long reg;
-
+
reg = (given >> 3) & 0x7;
if (given & (1 << 6))
reg += 8;
-
+
func (stream, "%s", arm_regnames[reg]);
}
break;
@@ -1305,11 +1305,11 @@ print_insn_thumb (pc, info, given)
case 'D':
{
long reg;
-
+
reg = given & 0x7;
if (given & (1 << 7))
reg += 8;
-
+
func (stream, "%s", arm_regnames[reg]);
}
break;
@@ -1331,9 +1331,9 @@ print_insn_thumb (pc, info, given)
{
int started = 0;
int reg;
-
+
func (stream, "{");
-
+
/* It would be nice if we could spot
ranges, and generate the rS-rE format: */
for (reg = 0; (reg < 8); reg++)
@@ -1365,12 +1365,12 @@ print_insn_thumb (pc, info, given)
break;
- case '0': case '1': case '2': case '3': case '4':
+ case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
{
int bitstart = *c++ - '0';
int bitend = 0;
-
+
while (*c >= '0' && *c <= '9')
bitstart = (bitstart * 10) + *c++ - '0';
@@ -1379,7 +1379,7 @@ print_insn_thumb (pc, info, given)
case '-':
{
long reg;
-
+
c++;
while (*c >= '0' && *c <= '9')
bitend = (bitend * 10) + *c++ - '0';
@@ -1478,11 +1478,11 @@ parse_arm_disassembler_option (option)
{
if (option == NULL)
return;
-
+
if (strneq (option, "reg-names-", 10))
{
int i;
-
+
option += 10;
for (i = NUM_ARM_REGNAMES; i--;)
@@ -1491,7 +1491,7 @@ parse_arm_disassembler_option (option)
regname_selected = i;
break;
}
-
+
if (i < 0)
fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
}
@@ -1501,7 +1501,7 @@ parse_arm_disassembler_option (option)
force_thumb = 0;
else
fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
-
+
return;
}
@@ -1512,7 +1512,7 @@ parse_disassembler_options (options)
char * options;
{
char * space;
-
+
if (options == NULL)
return;
@@ -1550,25 +1550,25 @@ print_insn_arm (pc, info)
if (info->disassembler_options)
{
parse_disassembler_options (info->disassembler_options);
-
+
/* To avoid repeated parsing of these options, we remove them here. */
info->disassembler_options = NULL;
}
-
+
is_thumb = force_thumb;
if (pc & 1)
{
is_thumb = 1;
pc &= ~(bfd_vma) 1;
}
-
+
#if 0
if (!is_thumb && info->symbols != NULL)
{
if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
{
coff_symbol_type * cs;
-
+
cs = coffsymbol (*info->symbols);
is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT
|| cs->native->u.syment.n_sclass == C_THUMBSTAT
@@ -1580,15 +1580,15 @@ print_insn_arm (pc, info)
{
elf_symbol_type * es;
unsigned int type;
-
+
es = *(elf_symbol_type **)(info->symbols);
type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
-
+
is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
}
}
#endif
-
+
little = (info->endian == BFD_ENDIAN_LITTLE);
info->bytes_per_chunk = 4;
info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
@@ -1599,17 +1599,17 @@ print_insn_arm (pc, info)
if (status != 0 && is_thumb)
{
info->bytes_per_chunk = 2;
-
+
status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
b[3] = b[2] = 0;
}
-
+
if (status != 0)
{
info->memory_error_func (status, pc, info);
return -1;
}
-
+
given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
}
else
@@ -1621,13 +1621,13 @@ print_insn_arm (pc, info)
info->memory_error_func (status, pc, info);
return -1;
}
-
+
if (is_thumb)
{
if (pc & 0x2)
{
given = (b[2] << 8) | b[3];
-
+
status = info->read_memory_func
((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
if (status != 0)
@@ -1635,7 +1635,7 @@ print_insn_arm (pc, info)
info->memory_error_func (status, pc + 4, info);
return -1;
}
-
+
given |= (b[0] << 24) | (b[1] << 16);
}
else
@@ -1644,7 +1644,7 @@ print_insn_arm (pc, info)
else
given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
}
-
+
if (info->flags & INSN_HAS_RELOC)
/* If the instruction has a reloc associated with it, then
the offset field in the instruction will actually be the
@@ -1668,7 +1668,7 @@ print_arm_disassembler_options (FILE * stream)
fprintf (stream, _("\n\
The following ARM specific disassembler options are supported for use with\n\
the -M switch:\n"));
-
+
for (i = NUM_ARM_REGNAMES; i--;)
fprintf (stream, " reg-names-%s %*c%s\n",
regnames[i].name,
diff --git a/arm-semi.c b/arm-semi.c
index 4ddbc73c2..ff7a343bc 100644
--- a/arm-semi.c
+++ b/arm-semi.c
@@ -1,6 +1,6 @@
/*
* Arm "Angel" semihosting syscalls
- *
+ *
* Copyright (c) 2005, 2007 CodeSourcery.
* Written by Paul Brook.
*
@@ -112,69 +112,26 @@ static inline uint32_t set_swi_errno(CPUState *env, uint32_t code)
return code;
}
-static uint32_t softmmu_tget32(CPUState *env, uint32_t addr)
-{
- uint32_t val;
-
- cpu_memory_rw_debug(env, addr, (uint8_t *)&val, 4, 0);
- return tswap32(val);
-}
-static uint32_t softmmu_tget8(CPUState *env, uint32_t addr)
-{
- uint8_t val;
-
- cpu_memory_rw_debug(env, addr, &val, 1, 0);
- return val;
-}
-#define tget32(p) softmmu_tget32(env, p)
-#define tget8(p) softmmu_tget8(env, p)
-
-static void *softmmu_lock_user(CPUState *env, uint32_t addr, uint32_t len,
- int copy)
-{
- char *p;
- /* TODO: Make this something that isn't fixed size. */
- p = malloc(len);
- if (copy)
- cpu_memory_rw_debug(env, addr, p, len, 0);
- return p;
-}
-#define lock_user(p, len, copy) softmmu_lock_user(env, p, len, copy)
-static char *softmmu_lock_user_string(CPUState *env, uint32_t addr)
-{
- char *p;
- char *s;
- uint8_t c;
- /* TODO: Make this something that isn't fixed size. */
- s = p = malloc(1024);
- do {
- cpu_memory_rw_debug(env, addr, &c, 1, 0);
- addr++;
- *(p++) = c;
- } while (c);
- return s;
-}
-#define lock_user_string(p) softmmu_lock_user_string(env, p)
-static void softmmu_unlock_user(CPUState *env, void *p, target_ulong addr,
- target_ulong len)
-{
- if (len)
- cpu_memory_rw_debug(env, addr, p, len, 1);
- free(p);
-}
-#define unlock_user(s, args, len) softmmu_unlock_user(env, s, args, len)
+#include "softmmu-semi.h"
#endif
static target_ulong arm_semi_syscall_len;
+#if !defined(CONFIG_USER_ONLY)
+static target_ulong syscall_err;
+#endif
+
static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
{
#ifdef CONFIG_USER_ONLY
TaskState *ts = env->opaque;
#endif
+
if (ret == (target_ulong)-1) {
#ifdef CONFIG_USER_ONLY
ts->swi_errno = err;
+#else
+ syscall_err = err;
#endif
env->regs[0] = ret;
} else {
@@ -194,6 +151,20 @@ static void arm_semi_cb(CPUState *env, target_ulong ret, target_ulong err)
}
}
+static void arm_semi_flen_cb(CPUState *env, target_ulong ret, target_ulong err)
+{
+ /* The size is always stored in big-endian order, extract
+ the value. We assume the size always fit in 32 bits. */
+ uint32_t size;
+ cpu_memory_rw_debug(env, env->regs[13]-64+32, (uint8_t *)&size, 4, 0);
+ env->regs[0] = be32_to_cpu(size);
+#ifdef CONFIG_USER_ONLY
+ ((TaskState *)env->opaque)->swi_errno = err;
+#else
+ syscall_err = err;
+#endif
+}
+
#define ARG(n) tget32(args + (n) * 4)
#define SET_ARG(n, val) tput32(args + (n) * 4,val)
uint32_t do_arm_semihosting(CPUState *env)
@@ -223,8 +194,8 @@ uint32_t do_arm_semihosting(CPUState *env)
return STDOUT_FILENO;
}
if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0), (int)ARG(2),
- gdb_open_modeflags[ARG(1)]);
+ gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0),
+ (int)ARG(2)+1, gdb_open_modeflags[ARG(1)]);
return env->regs[0];
} else {
ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
@@ -302,7 +273,7 @@ uint32_t do_arm_semihosting(CPUState *env)
}
case SYS_SEEK:
if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "fseek,%x,%x,0", ARG(0), ARG(1));
+ gdb_do_syscall(arm_semi_cb, "lseek,%x,%x,0", ARG(0), ARG(1));
return env->regs[0];
} else {
ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET));
@@ -312,8 +283,9 @@ uint32_t do_arm_semihosting(CPUState *env)
}
case SYS_FLEN:
if (use_gdb_syscalls()) {
- /* TODO: Use stat syscall. */
- return -1;
+ gdb_do_syscall(arm_semi_flen_cb, "fstat,%x,%x",
+ ARG(0), env->regs[13]-64);
+ return env->regs[0];
} else {
struct stat buf;
ret = set_swi_errno(ts, fstat(ARG(0), &buf));
@@ -326,7 +298,7 @@ uint32_t do_arm_semihosting(CPUState *env)
return -1;
case SYS_REMOVE:
if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1));
+ gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)+1);
ret = env->regs[0];
} else {
s = lock_user_string(ARG(0));
@@ -337,7 +309,7 @@ uint32_t do_arm_semihosting(CPUState *env)
case SYS_RENAME:
if (use_gdb_syscalls()) {
gdb_do_syscall(arm_semi_cb, "rename,%s,%s",
- ARG(0), (int)ARG(1), ARG(2), (int)ARG(3));
+ ARG(0), (int)ARG(1)+1, ARG(2), (int)ARG(3)+1);
return env->regs[0];
} else {
char *s2;
@@ -354,7 +326,7 @@ uint32_t do_arm_semihosting(CPUState *env)
return set_swi_errno(ts, time(NULL));
case SYS_SYSTEM:
if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1));
+ gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)+1);
return env->regs[0];
} else {
s = lock_user_string(ARG(0));
@@ -365,7 +337,7 @@ uint32_t do_arm_semihosting(CPUState *env)
#ifdef CONFIG_USER_ONLY
return ts->swi_errno;
#else
- return 0;
+ return syscall_err;
#endif
case SYS_GET_CMDLINE:
#ifdef CONFIG_USER_ONLY
@@ -429,7 +401,7 @@ uint32_t do_arm_semihosting(CPUState *env)
}
ts->heap_limit = limit;
}
-
+
ptr = lock_user(ARG(0), 16, 0);
ptr[0] = tswap32(ts->heap_base);
ptr[1] = tswap32(ts->heap_limit);
diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 71e523566..a573a380a 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -50,13 +50,15 @@ static struct {
unsigned int period_size_out;
unsigned int threshold;
- int buffer_size_in_overriden;
- int period_size_in_overriden;
+ int buffer_size_in_overridden;
+ int period_size_in_overridden;
- int buffer_size_out_overriden;
- int period_size_out_overriden;
+ int buffer_size_out_overridden;
+ int period_size_out_overridden;
int verbose;
} conf = {
+#define DEFAULT_BUFFER_SIZE 1024
+#define DEFAULT_PERIOD_SIZE 256
#ifdef HIGH_LATENCY
.size_in_usec_in = 1,
.size_in_usec_out = 1,
@@ -69,16 +71,14 @@ static struct {
.buffer_size_out = 400000,
.period_size_out = 400000 / 4,
#else
-#define DEFAULT_BUFFER_SIZE 1024
-#define DEFAULT_PERIOD_SIZE 256
.buffer_size_in = DEFAULT_BUFFER_SIZE * 4,
.period_size_in = DEFAULT_PERIOD_SIZE * 4,
.buffer_size_out = DEFAULT_BUFFER_SIZE,
.period_size_out = DEFAULT_PERIOD_SIZE,
- .buffer_size_in_overriden = 0,
- .buffer_size_out_overriden = 0,
- .period_size_in_overriden = 0,
- .period_size_out_overriden = 0,
+ .buffer_size_in_overridden = 0,
+ .buffer_size_out_overridden = 0,
+ .period_size_in_overridden = 0,
+ .period_size_out_overridden = 0,
#endif
.threshold = 0,
.verbose = 0
@@ -157,6 +157,12 @@ static int aud_to_alsafmt (audfmt_e fmt)
case AUD_FMT_U16:
return SND_PCM_FORMAT_U16_LE;
+ case AUD_FMT_S32:
+ return SND_PCM_FORMAT_S32_LE;
+
+ case AUD_FMT_U32:
+ return SND_PCM_FORMAT_U32_LE;
+
default:
dolog ("Internal logic error: Bad audio format %d\n", fmt);
#ifdef DEBUG_AUDIO
@@ -199,6 +205,26 @@ static int alsa_to_audfmt (int alsafmt, audfmt_e *fmt, int *endianness)
*fmt = AUD_FMT_U16;
break;
+ case SND_PCM_FORMAT_S32_LE:
+ *endianness = 0;
+ *fmt = AUD_FMT_S32;
+ break;
+
+ case SND_PCM_FORMAT_U32_LE:
+ *endianness = 0;
+ *fmt = AUD_FMT_U32;
+ break;
+
+ case SND_PCM_FORMAT_S32_BE:
+ *endianness = 1;
+ *fmt = AUD_FMT_S32;
+ break;
+
+ case SND_PCM_FORMAT_U32_BE:
+ *endianness = 1;
+ *fmt = AUD_FMT_U32;
+ break;
+
default:
dolog ("Unrecognized audio format %d\n", alsafmt);
return -1;
@@ -388,8 +414,8 @@ static int alsa_open (int in, struct alsa_params_req *req,
}
else {
if (period_size < minval) {
- if ((in && conf.period_size_in_overriden)
- || (!in && conf.period_size_out_overriden)) {
+ if ((in && conf.period_size_in_overridden)
+ || (!in && conf.period_size_out_overridden)) {
dolog ("%s period size(%d) is less "
"than minmal period size(%ld)\n",
typ,
@@ -424,8 +450,8 @@ static int alsa_open (int in, struct alsa_params_req *req,
}
else {
if (buffer_size < minval) {
- if ((in && conf.buffer_size_in_overriden)
- || (!in && conf.buffer_size_out_overriden)) {
+ if ((in && conf.buffer_size_in_overridden)
+ || (!in && conf.buffer_size_out_overridden)) {
dolog (
"%s buffer size(%d) is less "
"than minimal buffer size(%ld)\n",
@@ -919,16 +945,16 @@ static struct audio_option alsa_options[] = {
{"DAC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_out,
"DAC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
{"DAC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_out,
- "DAC period size", &conf.period_size_out_overriden, 0},
+ "DAC period size", &conf.period_size_out_overridden, 0},
{"DAC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_out,
- "DAC buffer size", &conf.buffer_size_out_overriden, 0},
+ "DAC buffer size", &conf.buffer_size_out_overridden, 0},
{"ADC_SIZE_IN_USEC", AUD_OPT_BOOL, &conf.size_in_usec_in,
"ADC period/buffer size in microseconds (otherwise in frames)", NULL, 0},
{"ADC_PERIOD_SIZE", AUD_OPT_INT, &conf.period_size_in,
- "ADC period size", &conf.period_size_in_overriden, 0},
+ "ADC period size", &conf.period_size_in_overridden, 0},
{"ADC_BUFFER_SIZE", AUD_OPT_INT, &conf.buffer_size_in,
- "ADC buffer size", &conf.buffer_size_in_overriden, 0},
+ "ADC buffer size", &conf.buffer_size_in_overridden, 0},
{"THRESHOLD", AUD_OPT_INT, &conf.threshold,
"(undocumented)", NULL, 0},
diff --git a/audio/audio.c b/audio/audio.c
index 556e6fdbc..4248c1401 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -80,7 +80,8 @@ static struct {
{
44100, /* freq */
2, /* nchannels */
- AUD_FMT_S16 /* fmt */
+ AUD_FMT_S16, /* fmt */
+ AUDIO_HOST_ENDIANNESS
}
},
@@ -91,7 +92,8 @@ static struct {
{
44100, /* freq */
2, /* nchannels */
- AUD_FMT_S16 /* fmt */
+ AUD_FMT_S16, /* fmt */
+ AUDIO_HOST_ENDIANNESS
}
},
@@ -166,6 +168,25 @@ int audio_bug (const char *funcname, int cond)
}
#endif
+static inline int audio_bits_to_index (int bits)
+{
+ switch (bits) {
+ case 8:
+ return 0;
+
+ case 16:
+ return 1;
+
+ case 32:
+ return 2;
+
+ default:
+ audio_bug ("bits_to_index", 1);
+ AUD_log (NULL, "invalid bits %d\n", bits);
+ return 0;
+ }
+}
+
void *audio_calloc (const char *funcname, int nmemb, size_t size)
{
int cond;
@@ -227,6 +248,12 @@ const char *audio_audfmt_to_string (audfmt_e fmt)
case AUD_FMT_S16:
return "S16";
+
+ case AUD_FMT_U32:
+ return "U32";
+
+ case AUD_FMT_S32:
+ return "S32";
}
dolog ("Bogus audfmt %d returning S16\n", fmt);
@@ -243,6 +270,10 @@ audfmt_e audio_string_to_audfmt (const char *s, audfmt_e defval, int *defaultp)
*defaultp = 0;
return AUD_FMT_U16;
}
+ else if (!strcasecmp (s, "u32")) {
+ *defaultp = 0;
+ return AUD_FMT_U32;
+ }
else if (!strcasecmp (s, "s8")) {
*defaultp = 0;
return AUD_FMT_S8;
@@ -251,6 +282,10 @@ audfmt_e audio_string_to_audfmt (const char *s, audfmt_e defval, int *defaultp)
*defaultp = 0;
return AUD_FMT_S16;
}
+ else if (!strcasecmp (s, "s32")) {
+ *defaultp = 0;
+ return AUD_FMT_S32;
+ }
else {
dolog ("Bogus audio format `%s' using %s\n",
s, audio_audfmt_to_string (defval));
@@ -351,7 +386,7 @@ static void audio_print_options (const char *prefix,
const char *state = "default";
printf (" %s_%s: ", uprefix, opt->name);
- if (opt->overridenp && *opt->overridenp) {
+ if (opt->overriddenp && *opt->overriddenp) {
state = "current";
}
@@ -481,10 +516,10 @@ static void audio_process_options (const char *prefix,
break;
}
- if (!opt->overridenp) {
- opt->overridenp = &opt->overriden;
+ if (!opt->overriddenp) {
+ opt->overriddenp = &opt->overridden;
}
- *opt->overridenp = !def;
+ *opt->overriddenp = !def;
qemu_free (optname);
}
}
@@ -538,6 +573,8 @@ static int audio_validate_settings (audsettings_t *as)
case AUD_FMT_U8:
case AUD_FMT_S16:
case AUD_FMT_U16:
+ case AUD_FMT_S32:
+ case AUD_FMT_U32:
break;
default:
invalid = 1;
@@ -563,6 +600,12 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
case AUD_FMT_U16:
bits = 16;
break;
+
+ case AUD_FMT_S32:
+ sign = 1;
+ case AUD_FMT_U32:
+ bits = 32;
+ break;
}
return info->freq == as->freq
&& info->nchannels == as->nchannels
@@ -573,7 +616,7 @@ static int audio_pcm_info_eq (struct audio_pcm_info *info, audsettings_t *as)
void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
{
- int bits = 8, sign = 0;
+ int bits = 8, sign = 0, shift = 0;
switch (as->fmt) {
case AUD_FMT_S8:
@@ -585,6 +628,14 @@ void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
sign = 1;
case AUD_FMT_U16:
bits = 16;
+ shift = 1;
+ break;
+
+ case AUD_FMT_S32:
+ sign = 1;
+ case AUD_FMT_U32:
+ bits = 32;
+ shift = 2;
break;
}
@@ -592,7 +643,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, audsettings_t *as)
info->bits = bits;
info->sign = sign;
info->nchannels = as->nchannels;
- info->shift = (as->nchannels == 2) + (bits == 16);
+ info->shift = (as->nchannels == 2) + shift;
info->align = (1 << info->shift) - 1;
info->bytes_per_second = info->freq << info->shift;
info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS);
@@ -608,22 +659,49 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
memset (buf, 0x00, len << info->shift);
}
else {
- if (info->bits == 8) {
+ switch (info->bits) {
+ case 8:
memset (buf, 0x80, len << info->shift);
- }
- else {
- int i;
- uint16_t *p = buf;
- int shift = info->nchannels - 1;
- short s = INT16_MAX;
+ break;
- if (info->swap_endianness) {
- s = bswap16 (s);
+ case 16:
+ {
+ int i;
+ uint16_t *p = buf;
+ int shift = info->nchannels - 1;
+ short s = INT16_MAX;
+
+ if (info->swap_endianness) {
+ s = bswap16 (s);
+ }
+
+ for (i = 0; i < len << shift; i++) {
+ p[i] = s;
+ }
}
+ break;
+
+ case 32:
+ {
+ int i;
+ uint32_t *p = buf;
+ int shift = info->nchannels - 1;
+ int32_t s = INT32_MAX;
+
+ if (info->swap_endianness) {
+ s = bswap32 (s);
+ }
- for (i = 0; i < len << shift; i++) {
- p[i] = s;
+ for (i = 0; i < len << shift; i++) {
+ p[i] = s;
+ }
}
+ break;
+
+ default:
+ AUD_log (NULL, "audio_pcm_info_clear_buf: invalid bits %d\n",
+ info->bits);
+ break;
}
}
}
@@ -1811,7 +1889,7 @@ CaptureVoiceOut *AUD_add_capture (
[hw->info.nchannels == 2]
[hw->info.sign]
[hw->info.swap_endianness]
- [hw->info.bits == 16];
+ [audio_bits_to_index (hw->info.bits)];
LIST_INSERT_HEAD (&s->cap_head, cap, entries);
LIST_INSERT_HEAD (&cap->cb_head, cb, entries);
diff --git a/audio/audio.h b/audio/audio.h
index c097f391b..287cc5c73 100644
--- a/audio/audio.h
+++ b/audio/audio.h
@@ -33,7 +33,9 @@ typedef enum {
AUD_FMT_U8,
AUD_FMT_S8,
AUD_FMT_U16,
- AUD_FMT_S16
+ AUD_FMT_S16,
+ AUD_FMT_U32,
+ AUD_FMT_S32
} audfmt_e;
#ifdef WORDS_BIGENDIAN
diff --git a/audio/audio_int.h b/audio/audio_int.h
index 1a15d4ced..cd22a3088 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -44,8 +44,8 @@ struct audio_option {
audio_option_tag_e tag;
void *valp;
const char *descr;
- int *overridenp;
- int overriden;
+ int *overriddenp;
+ int overridden;
};
struct audio_callback {
diff --git a/audio/audio_template.h b/audio/audio_template.h
index 13e1c3efb..850e101d7 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -164,7 +164,7 @@ static int glue (audio_pcm_sw_init_, TYPE) (
[sw->info.nchannels == 2]
[sw->info.sign]
[sw->info.swap_endianness]
- [sw->info.bits == 16];
+ [audio_bits_to_index (sw->info.bits)];
sw->name = qemu_strdup (name);
err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
@@ -288,7 +288,7 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as)
[hw->info.nchannels == 2]
[hw->info.sign]
[hw->info.swap_endianness]
- [hw->info.bits == 16];
+ [audio_bits_to_index (hw->info.bits)];
if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
goto err1;
diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index 8512f122b..74d432f91 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -294,7 +294,6 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
UInt32 propertySize;
int err;
- int bits = 8;
const char *typ = "playback";
AudioValueRange frameRange;
@@ -305,10 +304,6 @@ static int coreaudio_init_out (HWVoiceOut *hw, audsettings_t *as)
return -1;
}
- if (as->fmt == AUD_FMT_S16 || as->fmt == AUD_FMT_U16) {
- bits = 16;
- }
-
audio_pcm_init_info (&hw->info, as);
/* open default output device */
diff --git a/audio/mixeng.c b/audio/mixeng.c
index 6308d4100..34cc1aeee 100644
--- a/audio/mixeng.c
+++ b/audio/mixeng.c
@@ -82,6 +82,7 @@
#undef IN_T
#undef SHIFT
+/* Unsigned 16 bit */
#define IN_T uint16_t
#define IN_MIN 0
#define IN_MAX USHRT_MAX
@@ -101,26 +102,72 @@
#undef IN_T
#undef SHIFT
-t_sample *mixeng_conv[2][2][2][2] = {
+/* Signed 32 bit */
+#define IN_T int32_t
+#define IN_MIN INT32_MIN
+#define IN_MAX INT32_MAX
+#define SIGNED
+#define SHIFT 32
+#define ENDIAN_CONVERSION natural
+#define ENDIAN_CONVERT(v) (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#define ENDIAN_CONVERSION swap
+#define ENDIAN_CONVERT(v) bswap32 (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#undef SIGNED
+#undef IN_MAX
+#undef IN_MIN
+#undef IN_T
+#undef SHIFT
+
+/* Unsigned 16 bit */
+#define IN_T uint32_t
+#define IN_MIN 0
+#define IN_MAX UINT32_MAX
+#define SHIFT 32
+#define ENDIAN_CONVERSION natural
+#define ENDIAN_CONVERT(v) (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#define ENDIAN_CONVERSION swap
+#define ENDIAN_CONVERT(v) bswap32 (v)
+#include "mixeng_template.h"
+#undef ENDIAN_CONVERT
+#undef ENDIAN_CONVERSION
+#undef IN_MAX
+#undef IN_MIN
+#undef IN_T
+#undef SHIFT
+
+t_sample *mixeng_conv[2][2][2][3] = {
{
{
{
conv_natural_uint8_t_to_mono,
- conv_natural_uint16_t_to_mono
+ conv_natural_uint16_t_to_mono,
+ conv_natural_uint32_t_to_mono
},
{
conv_natural_uint8_t_to_mono,
- conv_swap_uint16_t_to_mono
+ conv_swap_uint16_t_to_mono,
+ conv_swap_uint32_t_to_mono,
}
},
{
{
conv_natural_int8_t_to_mono,
- conv_natural_int16_t_to_mono
+ conv_natural_int16_t_to_mono,
+ conv_natural_int32_t_to_mono
},
{
conv_natural_int8_t_to_mono,
- conv_swap_int16_t_to_mono
+ conv_swap_int16_t_to_mono,
+ conv_swap_int32_t_to_mono
}
}
},
@@ -128,46 +175,54 @@ t_sample *mixeng_conv[2][2][2][2] = {
{
{
conv_natural_uint8_t_to_stereo,
- conv_natural_uint16_t_to_stereo
+ conv_natural_uint16_t_to_stereo,
+ conv_natural_uint32_t_to_stereo
},
{
conv_natural_uint8_t_to_stereo,
- conv_swap_uint16_t_to_stereo
+ conv_swap_uint16_t_to_stereo,
+ conv_swap_uint32_t_to_stereo
}
},
{
{
conv_natural_int8_t_to_stereo,
- conv_natural_int16_t_to_stereo
+ conv_natural_int16_t_to_stereo,
+ conv_natural_int32_t_to_stereo
},
{
conv_natural_int8_t_to_stereo,
- conv_swap_int16_t_to_stereo
+ conv_swap_int16_t_to_stereo,
+ conv_swap_int32_t_to_stereo,
}
}
}
};
-f_sample *mixeng_clip[2][2][2][2] = {
+f_sample *mixeng_clip[2][2][2][3] = {
{
{
{
clip_natural_uint8_t_from_mono,
- clip_natural_uint16_t_from_mono
+ clip_natural_uint16_t_from_mono,
+ clip_natural_uint32_t_from_mono
},
{
clip_natural_uint8_t_from_mono,
- clip_swap_uint16_t_from_mono
+ clip_swap_uint16_t_from_mono,
+ clip_swap_uint32_t_from_mono
}
},
{
{
clip_natural_int8_t_from_mono,
- clip_natural_int16_t_from_mono
+ clip_natural_int16_t_from_mono,
+ clip_natural_int32_t_from_mono
},
{
clip_natural_int8_t_from_mono,
- clip_swap_int16_t_from_mono
+ clip_swap_int16_t_from_mono,
+ clip_swap_int32_t_from_mono
}
}
},
@@ -175,21 +230,25 @@ f_sample *mixeng_clip[2][2][2][2] = {
{
{
clip_natural_uint8_t_from_stereo,
- clip_natural_uint16_t_from_stereo
+ clip_natural_uint16_t_from_stereo,
+ clip_natural_uint32_t_from_stereo
},
{
clip_natural_uint8_t_from_stereo,
- clip_swap_uint16_t_from_stereo
+ clip_swap_uint16_t_from_stereo,
+ clip_swap_uint32_t_from_stereo
}
},
{
{
clip_natural_int8_t_from_stereo,
- clip_natural_int16_t_from_stereo
+ clip_natural_int16_t_from_stereo,
+ clip_natural_int32_t_from_stereo
},
{
clip_natural_int8_t_from_stereo,
- clip_swap_int16_t_from_stereo
+ clip_swap_int16_t_from_stereo,
+ clip_swap_int32_t_from_stereo
}
}
}
diff --git a/audio/mixeng.h b/audio/mixeng.h
index 9e3bac174..95b68df6a 100644
--- a/audio/mixeng.h
+++ b/audio/mixeng.h
@@ -37,8 +37,8 @@ typedef void (t_sample) (st_sample_t *dst, const void *src,
int samples, volume_t *vol);
typedef void (f_sample) (void *dst, const st_sample_t *src, int samples);
-extern t_sample *mixeng_conv[2][2][2][2];
-extern f_sample *mixeng_clip[2][2][2][2];
+extern t_sample *mixeng_conv[2][2][2][3];
+extern f_sample *mixeng_clip[2][2][2][3];
void *st_rate_start (int inrate, int outrate);
void st_rate_flow (void *opaque, st_sample_t *ibuf, st_sample_t *obuf,
diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index 125e4c8ff..cedcea45f 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -21,10 +21,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/ioctl.h>
+#ifdef __OpenBSD__
+#include <soundcard.h>
+#else
#include <sys/soundcard.h>
+#endif
#include "vl.h"
#define AUDIO_CAP "oss"
diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
index f2a6896a5..11edab08d 100644
--- a/audio/sdlaudio.c
+++ b/audio/sdlaudio.c
@@ -25,6 +25,13 @@
#include <SDL_thread.h>
#include "vl.h"
+#ifndef _WIN32
+#ifdef __sun__
+#define _POSIX_PTHREAD_SEMANTICS 1
+#endif
+#include <signal.h>
+#endif
+
#define AUDIO_CAP "sdl"
#include "audio_int.h"
@@ -177,11 +184,22 @@ static int sdl_to_audfmt (int sdlfmt, audfmt_e *fmt, int *endianess)
static int sdl_open (SDL_AudioSpec *req, SDL_AudioSpec *obt)
{
int status;
+#ifndef _WIN32
+ sigset_t new, old;
+
+ /* Make sure potential threads created by SDL don't hog signals. */
+ sigfillset (&new);
+ pthread_sigmask (SIG_BLOCK, &new, &old);
+#endif
status = SDL_OpenAudio (req, obt);
if (status) {
sdl_logerr ("SDL_OpenAudio failed\n");
}
+
+#ifndef _WIN32
+ pthread_sigmask (SIG_SETMASK, &old, 0);
+#endif
return status;
}
diff --git a/audio/wavaudio.c b/audio/wavaudio.c
index a552b7e97..2dbc58cbe 100644
--- a/audio/wavaudio.c
+++ b/audio/wavaudio.c
@@ -41,7 +41,8 @@ static struct {
{
44100,
2,
- AUD_FMT_S16
+ AUD_FMT_S16,
+ AUDIO_HOST_ENDIANNESS
},
"qemu.wav"
};
@@ -131,6 +132,11 @@ static int wav_init_out (HWVoiceOut *hw, audsettings_t *as)
case AUD_FMT_U16:
bits16 = 1;
break;
+
+ case AUD_FMT_S32:
+ case AUD_FMT_U32:
+ dolog ("WAVE files can not handle 32bit formats\n");
+ return -1;
}
hdr[34] = bits16 ? 0x10 : 0x08;
diff --git a/audio/wavcapture.c b/audio/wavcapture.c
index d915fa02b..4810fa30d 100644
--- a/audio/wavcapture.c
+++ b/audio/wavcapture.c
@@ -37,15 +37,15 @@ static void wav_destroy (void *opaque)
if (wav->f) {
le_store (rlen, rifflen, 4);
le_store (dlen, datalen, 4);
-
+
qemu_fseek (wav->f, 4, SEEK_SET);
qemu_put_buffer (wav->f, rlen, 4);
-
+
qemu_fseek (wav->f, 32, SEEK_CUR);
qemu_put_buffer (wav->f, dlen, 4);
qemu_fclose (wav->f);
}
-
+
qemu_free (wav->path);
}
diff --git a/block-bochs.c b/block-bochs.c
index 35e2a6cf0..9baea9b6f 100644
--- a/block-bochs.c
+++ b/block-bochs.c
@@ -1,9 +1,9 @@
/*
* Block driver for the various disk image formats used by Bochs
* Currently only for "growing" type in read-only mode
- *
+ *
* Copyright (c) 2005 Alex Beregszaszi
- *
+ *
* 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
@@ -44,7 +44,7 @@ struct bochs_header_v1 {
char subtype[16]; // "Undoable" / "Volatile" / "Growing"
uint32_t version;
uint32_t header; // size of header
-
+
union {
struct {
uint32_t catalog; // num of entries
@@ -64,7 +64,7 @@ struct bochs_header {
char subtype[16]; // "Undoable" / "Volatile" / "Growing"
uint32_t version;
uint32_t header; // size of header
-
+
union {
struct {
uint32_t catalog; // num of entries
@@ -83,9 +83,9 @@ typedef struct BDRVBochsState {
uint32_t *catalog_bitmap;
int catalog_size;
-
+
int data_offset;
-
+
int bitmap_blocks;
int extent_blocks;
int extent_size;
@@ -94,7 +94,7 @@ typedef struct BDRVBochsState {
static int bochs_probe(const uint8_t *buf, int buf_size, const char *filename)
{
const struct bochs_header *bochs = (const void *)buf;
-
+
if (buf_size < HEADER_SIZE)
return 0;
@@ -121,9 +121,9 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
if (fd < 0)
return -1;
}
-
+
bs->read_only = 1; // no write support yet
-
+
s->fd = fd;
if (read(fd, &bochs, sizeof(bochs)) != sizeof(bochs)) {
@@ -161,7 +161,7 @@ static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
s->bitmap_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.bitmap) - 1) / 512;
s->extent_blocks = 1 + (le32_to_cpu(bochs.extra.redolog.extent) - 1) / 512;
-
+
s->extent_size = le32_to_cpu(bochs.extra.redolog.extent);
return 0;
@@ -180,7 +180,7 @@ static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
// seek to sector
extent_index = offset / s->extent_size;
extent_offset = (offset % s->extent_size) / 512;
-
+
if (s->catalog_bitmap[extent_index] == 0xffffffff)
{
// fprintf(stderr, "page not allocated [%x - %x:%x]\n",
@@ -191,17 +191,17 @@ static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
bitmap_offset = s->data_offset + (512 * s->catalog_bitmap[extent_index] *
(s->extent_blocks + s->bitmap_blocks));
block_offset = bitmap_offset + (512 * (s->bitmap_blocks + extent_offset));
-
+
// fprintf(stderr, "sect: %x [ext i: %x o: %x] -> %x bitmap: %x block: %x\n",
// sector_num, extent_index, extent_offset,
// le32_to_cpu(s->catalog_bitmap[extent_index]),
// bitmap_offset, block_offset);
-
+
// read in bitmap for current extent
lseek(s->fd, bitmap_offset + (extent_offset / 8), SEEK_SET);
-
+
read(s->fd, &bitmap_entry, 1);
-
+
if (!((bitmap_entry >> (extent_offset % 8)) & 1))
{
// fprintf(stderr, "sector (%x) in bitmap not allocated\n",
@@ -210,11 +210,11 @@ static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
}
lseek(s->fd, block_offset, SEEK_SET);
-
+
return 0;
}
-static int bochs_read(BlockDriverState *bs, int64_t sector_num,
+static int bochs_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVBochsState *s = bs->opaque;
diff --git a/block-cloop.c b/block-cloop.c
index f51c32d1b..0c9ddb381 100644
--- a/block-cloop.c
+++ b/block-cloop.c
@@ -1,8 +1,8 @@
/*
* QEMU Block driver for CLOOP images
- *
+ *
* Copyright (c) 2004 Johannes E. Schindelin
- *
+ *
* 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
@@ -96,7 +96,7 @@ cloop_close:
if(inflateInit(&s->zstream) != Z_OK)
goto cloop_close;
s->current_block=s->n_blocks;
-
+
s->sectors_per_block = s->block_size/512;
bs->total_sectors = s->n_blocks*s->sectors_per_block;
return 0;
@@ -107,12 +107,12 @@ static inline int cloop_read_block(BDRVCloopState *s,int block_num)
if(s->current_block != block_num) {
int ret;
uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
-
+
lseek(s->fd, s->offsets[block_num], SEEK_SET);
ret = read(s->fd, s->compressed_block, bytes);
- if (ret != bytes)
+ if (ret != bytes)
return -1;
-
+
s->zstream.next_in = s->compressed_block;
s->zstream.avail_in = bytes;
s->zstream.next_out = s->uncompressed_block;
@@ -123,13 +123,13 @@ static inline int cloop_read_block(BDRVCloopState *s,int block_num)
ret = inflate(&s->zstream, Z_FINISH);
if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size)
return -1;
-
+
s->current_block = block_num;
}
return 0;
}
-static int cloop_read(BlockDriverState *bs, int64_t sector_num,
+static int cloop_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVCloopState *s = bs->opaque;
diff --git a/block-cow.c b/block-cow.c
index 07c8a7bf1..47a91e5ac 100644
--- a/block-cow.c
+++ b/block-cow.c
@@ -1,8 +1,8 @@
/*
* Block driver for the COW format
- *
+ *
* 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
@@ -56,7 +56,7 @@ static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
if (buf_size >= sizeof(struct cow_header_v2) &&
be32_to_cpu(cow_header->magic) == COW_MAGIC &&
- be32_to_cpu(cow_header->version) == COW_VERSION)
+ be32_to_cpu(cow_header->version) == COW_VERSION)
return 100;
else
return 0;
@@ -85,18 +85,18 @@ static int cow_open(BlockDriverState *bs, const char *filename, int flags)
be32_to_cpu(cow_header.version) != COW_VERSION) {
goto fail;
}
-
+
/* cow image found */
size = be64_to_cpu(cow_header.size);
bs->total_sectors = size / 512;
- pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
cow_header.backing_file);
-
+
/* mmap the bitmap */
s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
- s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size),
- s->cow_bitmap_size,
+ s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size),
+ s->cow_bitmap_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, s->fd, 0);
if (s->cow_bitmap_addr == MAP_FAILED)
@@ -143,24 +143,24 @@ static inline int is_changed(uint8_t *bitmap,
return changed;
}
-static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
+static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
BDRVCowState *s = bs->opaque;
return is_changed(s->cow_bitmap, sector_num, nb_sectors, pnum);
}
-static int cow_read(BlockDriverState *bs, int64_t sector_num,
+static int cow_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVCowState *s = bs->opaque;
int ret, n;
-
+
while (nb_sectors > 0) {
if (is_changed(s->cow_bitmap, sector_num, nb_sectors, &n)) {
lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
ret = read(s->fd, buf, n * 512);
- if (ret != n * 512)
+ if (ret != n * 512)
return -1;
} else {
if (bs->backing_hd) {
@@ -179,15 +179,15 @@ static int cow_read(BlockDriverState *bs, int64_t sector_num,
return 0;
}
-static int cow_write(BlockDriverState *bs, int64_t sector_num,
+static int cow_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVCowState *s = bs->opaque;
int ret, i;
-
+
lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
ret = write(s->fd, buf, nb_sectors * 512);
- if (ret != nb_sectors * 512)
+ if (ret != nb_sectors * 512)
return -1;
for (i = 0; i < nb_sectors; i++)
cow_set_bit(s->cow_bitmap, sector_num + i);
@@ -211,7 +211,7 @@ static int cow_create(const char *filename, int64_t image_sectors,
if (flags)
return -ENOTSUP;
- cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+ cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
if (cow_fd < 0)
return -1;
diff --git a/block-dmg.c b/block-dmg.c
index a883a23f8..681f4dc71 100644
--- a/block-dmg.c
+++ b/block-dmg.c
@@ -1,8 +1,8 @@
/*
* QEMU Block driver for DMG images
- *
+ *
* Copyright (c) 2004 Johannes E. Schindelin
- *
+ *
* 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
@@ -28,7 +28,7 @@
typedef struct BDRVDMGState {
int fd;
-
+
/* each chunk contains a certain number of sectors,
* offsets[i] is the offset in the .dmg file,
* lengths[i] is the length of the compressed chunk,
@@ -86,7 +86,7 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
bs->read_only = 1;
s->n_chunks = 0;
s->offsets = s->lengths = s->sectors = s->sectorcounts = 0;
-
+
/* read offset of info blocks */
if(lseek(s->fd,-0x1d8,SEEK_END)<0) {
dmg_close:
@@ -167,7 +167,7 @@ dmg_close:
goto dmg_close;
s->current_chunk = s->n_chunks;
-
+
return 0;
}
@@ -227,7 +227,7 @@ static inline int dmg_read_chunk(BDRVDMGState *s,int sector_num)
if (ret != s->lengths[chunk])
return -1;
-
+
s->zstream.next_in = s->compressed_chunk;
s->zstream.avail_in = s->lengths[chunk];
s->zstream.next_out = s->uncompressed_chunk;
@@ -253,7 +253,7 @@ static inline int dmg_read_chunk(BDRVDMGState *s,int sector_num)
return 0;
}
-static int dmg_read(BlockDriverState *bs, int64_t sector_num,
+static int dmg_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVDMGState *s = bs->opaque;
diff --git a/block-parallels.c b/block-parallels.c
new file mode 100644
index 000000000..b0fb99cee
--- /dev/null
+++ b/block-parallels.c
@@ -0,0 +1,176 @@
+/*
+ * Block driver for Parallels disk image format
+ *
+ * Copyright (c) 2007 Alex Beregszaszi
+ *
+ * This code is based on comparing different disk images created by Parallels.
+ *
+ * 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 "block_int.h"
+
+/**************************************************************/
+
+#define HEADER_MAGIC "WithoutFreeSpace"
+#define HEADER_VERSION 2
+#define HEADER_SIZE 64
+
+// always little-endian
+struct parallels_header {
+ char magic[16]; // "WithoutFreeSpace"
+ uint32_t version;
+ uint32_t heads;
+ uint32_t cylinders;
+ uint32_t tracks;
+ uint32_t catalog_entries;
+ uint32_t nb_sectors;
+ char padding[24];
+} __attribute__((packed));
+
+typedef struct BDRVParallelsState {
+ int fd;
+
+ uint32_t *catalog_bitmap;
+ int catalog_size;
+
+ int tracks;
+} BDRVParallelsState;
+
+static int parallels_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+ const struct parallels_header *ph = (const void *)buf;
+
+ if (buf_size < HEADER_SIZE)
+ return 0;
+
+ if (!memcmp(ph->magic, HEADER_MAGIC, 16) &&
+ (le32_to_cpu(ph->version) == HEADER_VERSION))
+ return 100;
+
+ return 0;
+}
+
+static int parallels_open(BlockDriverState *bs, const char *filename, int flags)
+{
+ BDRVParallelsState *s = bs->opaque;
+ int fd, i;
+ struct parallels_header ph;
+
+ fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
+ if (fd < 0) {
+ fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
+ if (fd < 0)
+ return -1;
+ }
+
+ bs->read_only = 1; // no write support yet
+
+ s->fd = fd;
+
+ if (read(fd, &ph, sizeof(ph)) != sizeof(ph))
+ goto fail;
+
+ if (memcmp(ph.magic, HEADER_MAGIC, 16) ||
+ (le32_to_cpu(ph.version) != HEADER_VERSION)) {
+ goto fail;
+ }
+
+ bs->total_sectors = le32_to_cpu(ph.nb_sectors);
+
+ if (lseek(s->fd, 64, SEEK_SET) != 64)
+ goto fail;
+
+ s->tracks = le32_to_cpu(ph.tracks);
+
+ s->catalog_size = le32_to_cpu(ph.catalog_entries);
+ s->catalog_bitmap = qemu_malloc(s->catalog_size * 4);
+ if (!s->catalog_bitmap)
+ goto fail;
+ if (read(s->fd, s->catalog_bitmap, s->catalog_size * 4) !=
+ s->catalog_size * 4)
+ goto fail;
+ for (i = 0; i < s->catalog_size; i++)
+ le32_to_cpus(&s->catalog_bitmap[i]);
+
+ return 0;
+fail:
+ if (s->catalog_bitmap)
+ qemu_free(s->catalog_bitmap);
+ close(fd);
+ return -1;
+}
+
+static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
+{
+ BDRVParallelsState *s = bs->opaque;
+ uint32_t index, offset, position;
+
+ index = sector_num / s->tracks;
+ offset = sector_num % s->tracks;
+
+ // not allocated
+ if ((index > s->catalog_size) || (s->catalog_bitmap[index] == 0))
+ return -1;
+
+ position = (s->catalog_bitmap[index] + offset) * 512;
+
+// fprintf(stderr, "sector: %llx index=%x offset=%x pointer=%x position=%x\n",
+// sector_num, index, offset, s->catalog_bitmap[index], position);
+
+ if (lseek(s->fd, position, SEEK_SET) != position)
+ return -1;
+
+ return 0;
+}
+
+static int parallels_read(BlockDriverState *bs, int64_t sector_num,
+ uint8_t *buf, int nb_sectors)
+{
+ BDRVParallelsState *s = bs->opaque;
+
+ while (nb_sectors > 0) {
+ if (!seek_to_sector(bs, sector_num)) {
+ if (read(s->fd, buf, 512) != 512)
+ return -1;
+ } else
+ memset(buf, 0, 512);
+ nb_sectors--;
+ sector_num++;
+ buf += 512;
+ }
+ return 0;
+}
+
+static void parallels_close(BlockDriverState *bs)
+{
+ BDRVParallelsState *s = bs->opaque;
+ qemu_free(s->catalog_bitmap);
+ close(s->fd);
+}
+
+BlockDriver bdrv_parallels = {
+ "parallels",
+ sizeof(BDRVParallelsState),
+ parallels_probe,
+ parallels_open,
+ parallels_read,
+ NULL,
+ parallels_close,
+};
diff --git a/block-qcow.c b/block-qcow.c
index d5333b379..9a0bca0e7 100644
--- a/block-qcow.c
+++ b/block-qcow.c
@@ -1,8 +1,8 @@
/*
* Block driver for the QCOW format
- *
+ *
* Copyright (c) 2004-2006 Fabrice Bellard
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
@@ -80,10 +80,10 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset);
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
{
const QCowHeader *cow_header = (const void *)buf;
-
+
if (buf_size >= sizeof(QCowHeader) &&
be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&
- be32_to_cpu(cow_header->version) == QCOW_VERSION)
+ be32_to_cpu(cow_header->version) == QCOW_VERSION)
return 100;
else
return 0;
@@ -108,7 +108,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
be64_to_cpus(&header.size);
be32_to_cpus(&header.crypt_method);
be64_to_cpus(&header.l1_table_offset);
-
+
if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION)
goto fail;
if (header.size <= 1 || header.cluster_bits < 9)
@@ -134,7 +134,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
if (!s->l1_table)
goto fail;
- if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
+ if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
s->l1_size * sizeof(uint64_t))
goto fail;
for(i = 0;i < s->l1_size; i++) {
@@ -151,7 +151,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
if (!s->cluster_data)
goto fail;
s->cluster_cache_offset = -1;
-
+
/* read the backing file name */
if (header.backing_file_offset != 0) {
len = header.backing_file_size;
@@ -177,7 +177,7 @@ static int qcow_set_key(BlockDriverState *bs, const char *key)
BDRVQcowState *s = bs->opaque;
uint8_t keybuf[16];
int len, i;
-
+
memset(keybuf, 0, 16);
len = strlen(key);
if (len > 16)
@@ -231,7 +231,7 @@ static void encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
for(i = 0; i < nb_sectors; i++) {
ivec.ll[0] = cpu_to_le64(sector_num);
ivec.ll[1] = 0;
- AES_cbc_encrypt(in_buf, out_buf, 512, key,
+ AES_cbc_encrypt(in_buf, out_buf, 512, key,
ivec.b, enc);
sector_num++;
in_buf += 512;
@@ -248,7 +248,7 @@ static void encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
*
* 2 to allocate a compressed cluster of size
* 'compressed_size'. 'compressed_size' must be > 0 and <
- * cluster_size
+ * cluster_size
*
* return 0 if not allocated.
*/
@@ -262,7 +262,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
uint64_t l2_offset, *l2_table, cluster_offset, tmp;
uint32_t min_count;
int new_l2_table;
-
+
l1_index = offset >> (s->l2_bits + s->cluster_bits);
l2_offset = s->l1_table[l1_index];
new_l2_table = 0;
@@ -276,7 +276,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
/* update the L1 entry */
s->l1_table[l1_index] = l2_offset;
tmp = cpu_to_be64(l2_offset);
- if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp),
+ if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp),
&tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
new_l2_table = 1;
@@ -309,7 +309,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
s->l2_size * sizeof(uint64_t))
return 0;
} else {
- if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
+ if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return 0;
}
@@ -318,7 +318,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
found:
l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
cluster_offset = be64_to_cpu(l2_table[l2_index]);
- if (!cluster_offset ||
+ if (!cluster_offset ||
((cluster_offset & QCOW_OFLAG_COMPRESSED) && allocate == 1)) {
if (!allocate)
return 0;
@@ -331,54 +331,54 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
if (decompress_cluster(s, cluster_offset) < 0)
return 0;
cluster_offset = bdrv_getlength(s->hd);
- cluster_offset = (cluster_offset + s->cluster_size - 1) &
+ cluster_offset = (cluster_offset + s->cluster_size - 1) &
~(s->cluster_size - 1);
/* write the cluster content */
- if (bdrv_pwrite(s->hd, cluster_offset, s->cluster_cache, s->cluster_size) !=
+ if (bdrv_pwrite(s->hd, cluster_offset, s->cluster_cache, s->cluster_size) !=
s->cluster_size)
return -1;
} else {
cluster_offset = bdrv_getlength(s->hd);
if (allocate == 1) {
/* round to cluster size */
- cluster_offset = (cluster_offset + s->cluster_size - 1) &
+ cluster_offset = (cluster_offset + s->cluster_size - 1) &
~(s->cluster_size - 1);
bdrv_truncate(s->hd, cluster_offset + s->cluster_size);
/* if encrypted, we must initialize the cluster
content which won't be written */
- if (s->crypt_method &&
+ if (s->crypt_method &&
(n_end - n_start) < s->cluster_sectors) {
uint64_t start_sect;
start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
memset(s->cluster_data + 512, 0x00, 512);
for(i = 0; i < s->cluster_sectors; i++) {
if (i < n_start || i >= n_end) {
- encrypt_sectors(s, start_sect + i,
- s->cluster_data,
+ encrypt_sectors(s, start_sect + i,
+ s->cluster_data,
s->cluster_data + 512, 1, 1,
&s->aes_encrypt_key);
- if (bdrv_pwrite(s->hd, cluster_offset + i * 512,
+ if (bdrv_pwrite(s->hd, cluster_offset + i * 512,
s->cluster_data, 512) != 512)
return -1;
}
}
}
} else {
- cluster_offset |= QCOW_OFLAG_COMPRESSED |
+ cluster_offset |= QCOW_OFLAG_COMPRESSED |
(uint64_t)compressed_size << (63 - s->cluster_bits);
}
}
/* update L2 table */
tmp = cpu_to_be64(cluster_offset);
l2_table[l2_index] = tmp;
- if (bdrv_pwrite(s->hd,
+ if (bdrv_pwrite(s->hd,
l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
}
return cluster_offset;
}
-static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num,
+static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
BDRVQcowState *s = bs->opaque;
@@ -420,7 +420,7 @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
inflateEnd(strm);
return 0;
}
-
+
static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
{
int ret, csize;
@@ -431,7 +431,7 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
csize = cluster_offset >> (63 - s->cluster_bits);
csize &= (s->cluster_size - 1);
ret = bdrv_pread(s->hd, coffset, s->cluster_data, csize);
- if (ret != csize)
+ if (ret != csize)
return -1;
if (decompress_buffer(s->cluster_cache, s->cluster_size,
s->cluster_data, csize) < 0) {
@@ -444,13 +444,13 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
#if 0
-static int qcow_read(BlockDriverState *bs, int64_t sector_num,
+static int qcow_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
int ret, index_in_cluster, n;
uint64_t cluster_offset;
-
+
while (nb_sectors > 0) {
cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
index_in_cluster = sector_num & (s->cluster_sectors - 1);
@@ -472,10 +472,10 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
} else {
ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
- if (ret != n * 512)
+ if (ret != n * 512)
return -1;
if (s->crypt_method) {
- encrypt_sectors(s, sector_num, buf, buf, n, 0,
+ encrypt_sectors(s, sector_num, buf, buf, n, 0,
&s->aes_decrypt_key);
}
}
@@ -487,32 +487,32 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
}
#endif
-static int qcow_write(BlockDriverState *bs, int64_t sector_num,
+static int qcow_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
int ret, index_in_cluster, n;
uint64_t cluster_offset;
-
+
while (nb_sectors > 0) {
index_in_cluster = sector_num & (s->cluster_sectors - 1);
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
- cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,
- index_in_cluster,
+ cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,
+ index_in_cluster,
index_in_cluster + n);
if (!cluster_offset)
return -1;
if (s->crypt_method) {
encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
&s->aes_encrypt_key);
- ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512,
+ ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512,
s->cluster_data, n * 512);
} else {
ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
}
- if (ret != n * 512)
+ if (ret != n * 512)
return -1;
nb_sectors -= n;
sector_num += n;
@@ -529,7 +529,7 @@ typedef struct QCowAIOCB {
int nb_sectors;
int n;
uint64_t cluster_offset;
- uint8_t *cluster_data;
+ uint8_t *cluster_data;
BlockDriverAIOCB *hd_aiocb;
} QCowAIOCB;
@@ -556,8 +556,8 @@ static void qcow_aio_read_cb(void *opaque, int ret)
/* nothing to do */
} else {
if (s->crypt_method) {
- encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf,
- acb->n, 0,
+ encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf,
+ acb->n, 0,
&s->aes_decrypt_key);
}
}
@@ -572,9 +572,9 @@ static void qcow_aio_read_cb(void *opaque, int ret)
qemu_aio_release(acb);
return;
}
-
+
/* prepare next AIO request */
- acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9,
+ acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9,
0, 0, 0, 0);
index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
acb->n = s->cluster_sectors - index_in_cluster;
@@ -597,7 +597,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
/* add AIO support for compressed blocks ? */
if (decompress_cluster(s, acb->cluster_offset) < 0)
goto fail;
- memcpy(acb->buf,
+ memcpy(acb->buf,
s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
goto redo;
} else {
@@ -606,7 +606,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
goto fail;
}
acb->hd_aiocb = bdrv_aio_read(s->hd,
- (acb->cluster_offset >> 9) + index_in_cluster,
+ (acb->cluster_offset >> 9) + index_in_cluster,
acb->buf, acb->n, qcow_aio_read_cb, acb);
if (acb->hd_aiocb == NULL)
goto fail;
@@ -627,7 +627,7 @@ static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
acb->buf = buf;
acb->nb_sectors = nb_sectors;
acb->n = 0;
- acb->cluster_offset = 0;
+ acb->cluster_offset = 0;
qcow_aio_read_cb(acb, 0);
return &acb->common;
@@ -661,13 +661,13 @@ static void qcow_aio_write_cb(void *opaque, int ret)
qemu_aio_release(acb);
return;
}
-
+
index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
acb->n = s->cluster_sectors - index_in_cluster;
if (acb->n > acb->nb_sectors)
acb->n = acb->nb_sectors;
- cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0,
- index_in_cluster,
+ cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0,
+ index_in_cluster,
index_in_cluster + acb->n);
if (!cluster_offset || (cluster_offset & 511) != 0) {
ret = -EIO;
@@ -681,15 +681,15 @@ static void qcow_aio_write_cb(void *opaque, int ret)
goto fail;
}
}
- encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf,
+ encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf,
acb->n, 1, &s->aes_encrypt_key);
src_buf = acb->cluster_data;
} else {
src_buf = acb->buf;
}
acb->hd_aiocb = bdrv_aio_write(s->hd,
- (cluster_offset >> 9) + index_in_cluster,
- src_buf, acb->n,
+ (cluster_offset >> 9) + index_in_cluster,
+ src_buf, acb->n,
qcow_aio_write_cb, acb);
if (acb->hd_aiocb == NULL)
goto fail;
@@ -701,7 +701,7 @@ static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
{
BDRVQcowState *s = bs->opaque;
QCowAIOCB *acb;
-
+
s->cluster_cache_offset = -1; /* disable compressed cache */
acb = qemu_aio_get(bs, cb, opaque);
@@ -712,7 +712,7 @@ static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
acb->buf = (uint8_t *)buf;
acb->nb_sectors = nb_sectors;
acb->n = 0;
-
+
qcow_aio_write_cb(acb, 0);
return &acb->common;
}
@@ -769,12 +769,12 @@ static int qcow_create(const char *filename, int64_t total_size,
l1_size = ((total_size * 512) + (1LL << shift) - 1) >> shift;
header.l1_table_offset = cpu_to_be64(header_size);
- if (flags) {
+ if (flags & BLOCK_FLAG_ENCRYPT) {
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
} else {
header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
}
-
+
/* write all the data */
write(fd, &header, sizeof(header));
if (backing_file) {
@@ -811,7 +811,7 @@ static int qcow_make_empty(BlockDriverState *bs)
/* XXX: put compressed sectors first, then all the cluster aligned
tables to avoid losing bytes in alignment */
-static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
+static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
@@ -830,7 +830,7 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
/* best compression, small window, no zlib header */
memset(&strm, 0, sizeof(strm));
ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,
- Z_DEFLATED, -12,
+ Z_DEFLATED, -12,
9, Z_DEFAULT_STRATEGY);
if (ret != 0) {
qemu_free(out_buf);
@@ -856,7 +856,7 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
/* could not compress: write normal cluster */
qcow_write(bs, sector_num, buf, s->cluster_sectors);
} else {
- cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
+ cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
out_len, 0, 0);
cluster_offset &= s->cluster_offset_mask;
if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
@@ -864,7 +864,7 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
return -1;
}
}
-
+
qemu_free(out_buf);
return 0;
}
diff --git a/block-qcow2.c b/block-qcow2.c
index a876ea2e2..b74fe348e 100644
--- a/block-qcow2.c
+++ b/block-qcow2.c
@@ -1,8 +1,8 @@
/*
* Block driver for the QCOW version 2 format
- *
+ *
* Copyright (c) 2004-2006 Fabrice Bellard
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
@@ -34,10 +34,10 @@
- Memory management by reference counts.
- Clusters which have a reference count of one have the bit
QCOW_OFLAG_COPIED to optimize write performance.
- - Size of compressed clusters is stored in sectors to reduce bit usage
+ - Size of compressed clusters is stored in sectors to reduce bit usage
in the cluster offsets.
- Support for storing additional data (such as the VM state) in the
- snapshots.
+ snapshots.
- If a backing store is used, the cluster size is not constrained
(could be backported to QCOW).
- L2 tables have always a size of one cluster.
@@ -45,7 +45,7 @@
//#define DEBUG_ALLOC
//#define DEBUG_ALLOC2
-
+
#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
#define QCOW_VERSION 2
@@ -152,22 +152,22 @@ typedef struct BDRVQcowState {
} BDRVQcowState;
static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset);
-static int qcow_read(BlockDriverState *bs, int64_t sector_num,
+static int qcow_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
static int qcow_read_snapshots(BlockDriverState *bs);
static void qcow_free_snapshots(BlockDriverState *bs);
static int refcount_init(BlockDriverState *bs);
static void refcount_close(BlockDriverState *bs);
static int get_refcount(BlockDriverState *bs, int64_t cluster_index);
-static int update_cluster_refcount(BlockDriverState *bs,
+static int update_cluster_refcount(BlockDriverState *bs,
int64_t cluster_index,
int addend);
-static void update_refcount(BlockDriverState *bs,
- int64_t offset, int64_t length,
+static void update_refcount(BlockDriverState *bs,
+ int64_t offset, int64_t length,
int addend);
static int64_t alloc_clusters(BlockDriverState *bs, int64_t size);
static int64_t alloc_bytes(BlockDriverState *bs, int size);
-static void free_clusters(BlockDriverState *bs,
+static void free_clusters(BlockDriverState *bs,
int64_t offset, int64_t size);
#ifdef DEBUG_ALLOC
static void check_refcounts(BlockDriverState *bs);
@@ -176,10 +176,10 @@ static void check_refcounts(BlockDriverState *bs);
static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
{
const QCowHeader *cow_header = (const void *)buf;
-
+
if (buf_size >= sizeof(QCowHeader) &&
be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&
- be32_to_cpu(cow_header->version) == QCOW_VERSION)
+ be32_to_cpu(cow_header->version) == QCOW_VERSION)
return 100;
else
return 0;
@@ -209,11 +209,11 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
be32_to_cpus(&header.refcount_table_clusters);
be64_to_cpus(&header.snapshots_offset);
be32_to_cpus(&header.nb_snapshots);
-
+
if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION)
goto fail;
- if (header.size <= 1 ||
- header.cluster_bits < 9 ||
+ if (header.size <= 1 ||
+ header.cluster_bits < 9 ||
header.cluster_bits > 16)
goto fail;
if (header.crypt_method > QCOW_CRYPT_AES)
@@ -231,7 +231,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;
s->cluster_offset_mask = (1LL << s->csize_shift) - 1;
s->refcount_table_offset = header.refcount_table_offset;
- s->refcount_table_size =
+ s->refcount_table_size =
header.refcount_table_clusters << (s->cluster_bits - 3);
s->snapshots_offset = header.snapshots_offset;
@@ -249,7 +249,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
if (!s->l1_table)
goto fail;
- if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
+ if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
s->l1_size * sizeof(uint64_t))
goto fail;
for(i = 0;i < s->l1_size; i++) {
@@ -267,7 +267,7 @@ static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
if (!s->cluster_data)
goto fail;
s->cluster_cache_offset = -1;
-
+
if (refcount_init(bs) < 0)
goto fail;
@@ -304,7 +304,7 @@ static int qcow_set_key(BlockDriverState *bs, const char *key)
BDRVQcowState *s = bs->opaque;
uint8_t keybuf[16];
int len, i;
-
+
memset(keybuf, 0, 16);
len = strlen(key);
if (len > 16)
@@ -358,7 +358,7 @@ static void encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
for(i = 0; i < nb_sectors; i++) {
ivec.ll[0] = cpu_to_le64(sector_num);
ivec.ll[1] = 0;
- AES_cbc_encrypt(in_buf, out_buf, 512, key,
+ AES_cbc_encrypt(in_buf, out_buf, 512, key,
ivec.b, enc);
sector_num++;
in_buf += 512;
@@ -379,12 +379,12 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
if (ret < 0)
return ret;
if (s->crypt_method) {
- encrypt_sectors(s, start_sect + n_start,
- s->cluster_data,
+ encrypt_sectors(s, start_sect + n_start,
+ s->cluster_data,
s->cluster_data, n, 1,
&s->aes_encrypt_key);
}
- ret = bdrv_write(s->hd, (cluster_offset >> 9) + n_start,
+ ret = bdrv_write(s->hd, (cluster_offset >> 9) + n_start,
s->cluster_data, n);
if (ret < 0)
return ret;
@@ -451,7 +451,7 @@ static int grow_l1_table(BlockDriverState *bs, int min_size)
/* write new table (align to cluster) */
new_l1_table_offset = alloc_clusters(bs, new_l1_size2);
-
+
for(i = 0; i < s->l1_size; i++)
new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
ret = bdrv_pwrite(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2);
@@ -459,7 +459,7 @@ static int grow_l1_table(BlockDriverState *bs, int min_size)
goto fail;
for(i = 0; i < s->l1_size; i++)
new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
-
+
/* set new table */
data64 = cpu_to_be64(new_l1_table_offset);
if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_table_offset),
@@ -489,7 +489,7 @@ static int grow_l1_table(BlockDriverState *bs, int min_size)
*
* 2 to allocate a compressed cluster of size
* 'compressed_size'. 'compressed_size' must be > 0 and <
- * cluster_size
+ * cluster_size
*
* return 0 if not allocated.
*/
@@ -501,7 +501,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
BDRVQcowState *s = bs->opaque;
int min_index, i, j, l1_index, l2_index, ret;
uint64_t l2_offset, *l2_table, cluster_offset, tmp, old_l2_offset;
-
+
l1_index = offset >> (s->l2_bits + s->cluster_bits);
if (l1_index >= s->l1_size) {
/* outside l1 table is allowed: we grow the table if needed */
@@ -521,7 +521,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
/* update the L1 entry */
s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
tmp = cpu_to_be64(l2_offset | QCOW_OFLAG_COPIED);
- if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp),
+ if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp),
&tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
min_index = l2_cache_new_entry(bs);
@@ -530,12 +530,12 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
if (old_l2_offset == 0) {
memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
} else {
- if (bdrv_pread(s->hd, old_l2_offset,
+ if (bdrv_pread(s->hd, old_l2_offset,
l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return 0;
}
- if (bdrv_pwrite(s->hd, l2_offset,
+ if (bdrv_pwrite(s->hd, l2_offset,
l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return 0;
@@ -563,7 +563,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
/* not found: load a new entry in the least used one */
min_index = l2_cache_new_entry(bs);
l2_table = s->l2_cache + (min_index << s->l2_bits);
- if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
+ if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
s->l2_size * sizeof(uint64_t))
return 0;
}
@@ -581,7 +581,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
/* free the cluster */
if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
int nb_csectors;
- nb_csectors = ((cluster_offset >> s->csize_shift) &
+ nb_csectors = ((cluster_offset >> s->csize_shift) &
s->csize_mask) + 1;
free_clusters(bs, (cluster_offset & s->cluster_offset_mask) & ~511,
nb_csectors * 512);
@@ -600,7 +600,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
written */
if ((n_end - n_start) < s->cluster_sectors) {
uint64_t start_sect;
-
+
start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
ret = copy_sectors(bs, start_sect,
cluster_offset, 0, n_start);
@@ -615,22 +615,22 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
} else {
int nb_csectors;
cluster_offset = alloc_bytes(bs, compressed_size);
- nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) -
+ nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) -
(cluster_offset >> 9);
- cluster_offset |= QCOW_OFLAG_COMPRESSED |
+ cluster_offset |= QCOW_OFLAG_COMPRESSED |
((uint64_t)nb_csectors << s->csize_shift);
/* compressed clusters never have the copied flag */
tmp = cpu_to_be64(cluster_offset);
}
/* update L2 table */
l2_table[l2_index] = tmp;
- if (bdrv_pwrite(s->hd,
+ if (bdrv_pwrite(s->hd,
l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))
return 0;
return cluster_offset;
}
-static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num,
+static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
BDRVQcowState *s = bs->opaque;
@@ -672,7 +672,7 @@ static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
inflateEnd(strm);
return 0;
}
-
+
static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
{
int ret, csize, nb_csectors, sector_offset;
@@ -697,7 +697,7 @@ static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
}
/* handle reading after the end of the backing file */
-static int backing_read1(BlockDriverState *bs,
+static int backing_read1(BlockDriverState *bs,
int64_t sector_num, uint8_t *buf, int nb_sectors)
{
int n1;
@@ -711,13 +711,13 @@ static int backing_read1(BlockDriverState *bs,
return n1;
}
-static int qcow_read(BlockDriverState *bs, int64_t sector_num,
+static int qcow_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
int ret, index_in_cluster, n, n1;
uint64_t cluster_offset;
-
+
while (nb_sectors > 0) {
cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
index_in_cluster = sector_num & (s->cluster_sectors - 1);
@@ -742,10 +742,10 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
} else {
ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
- if (ret != n * 512)
+ if (ret != n * 512)
return -1;
if (s->crypt_method) {
- encrypt_sectors(s, sector_num, buf, buf, n, 0,
+ encrypt_sectors(s, sector_num, buf, buf, n, 0,
&s->aes_decrypt_key);
}
}
@@ -756,32 +756,32 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
return 0;
}
-static int qcow_write(BlockDriverState *bs, int64_t sector_num,
+static int qcow_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
int ret, index_in_cluster, n;
uint64_t cluster_offset;
-
+
while (nb_sectors > 0) {
index_in_cluster = sector_num & (s->cluster_sectors - 1);
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
- cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,
- index_in_cluster,
+ cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,
+ index_in_cluster,
index_in_cluster + n);
if (!cluster_offset)
return -1;
if (s->crypt_method) {
encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
&s->aes_encrypt_key);
- ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512,
+ ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512,
s->cluster_data, n * 512);
} else {
ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
}
- if (ret != n * 512)
+ if (ret != n * 512)
return -1;
nb_sectors -= n;
sector_num += n;
@@ -798,7 +798,7 @@ typedef struct QCowAIOCB {
int nb_sectors;
int n;
uint64_t cluster_offset;
- uint8_t *cluster_data;
+ uint8_t *cluster_data;
BlockDriverAIOCB *hd_aiocb;
} QCowAIOCB;
@@ -825,8 +825,8 @@ static void qcow_aio_read_cb(void *opaque, int ret)
/* nothing to do */
} else {
if (s->crypt_method) {
- encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf,
- acb->n, 0,
+ encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf,
+ acb->n, 0,
&s->aes_decrypt_key);
}
}
@@ -841,9 +841,9 @@ static void qcow_aio_read_cb(void *opaque, int ret)
qemu_aio_release(acb);
return;
}
-
+
/* prepare next AIO request */
- acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9,
+ acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9,
0, 0, 0, 0);
index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
acb->n = s->cluster_sectors - index_in_cluster;
@@ -853,10 +853,10 @@ static void qcow_aio_read_cb(void *opaque, int ret)
if (!acb->cluster_offset) {
if (bs->backing_hd) {
/* read from the base image */
- n1 = backing_read1(bs->backing_hd, acb->sector_num,
+ n1 = backing_read1(bs->backing_hd, acb->sector_num,
acb->buf, acb->n);
if (n1 > 0) {
- acb->hd_aiocb = bdrv_aio_read(bs->backing_hd, acb->sector_num,
+ acb->hd_aiocb = bdrv_aio_read(bs->backing_hd, acb->sector_num,
acb->buf, acb->n, qcow_aio_read_cb, acb);
if (acb->hd_aiocb == NULL)
goto fail;
@@ -872,7 +872,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
/* add AIO support for compressed blocks ? */
if (decompress_cluster(s, acb->cluster_offset) < 0)
goto fail;
- memcpy(acb->buf,
+ memcpy(acb->buf,
s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
goto redo;
} else {
@@ -881,7 +881,7 @@ static void qcow_aio_read_cb(void *opaque, int ret)
goto fail;
}
acb->hd_aiocb = bdrv_aio_read(s->hd,
- (acb->cluster_offset >> 9) + index_in_cluster,
+ (acb->cluster_offset >> 9) + index_in_cluster,
acb->buf, acb->n, qcow_aio_read_cb, acb);
if (acb->hd_aiocb == NULL)
goto fail;
@@ -948,13 +948,13 @@ static void qcow_aio_write_cb(void *opaque, int ret)
qemu_aio_release(acb);
return;
}
-
+
index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
acb->n = s->cluster_sectors - index_in_cluster;
if (acb->n > acb->nb_sectors)
acb->n = acb->nb_sectors;
- cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0,
- index_in_cluster,
+ cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0,
+ index_in_cluster,
index_in_cluster + acb->n);
if (!cluster_offset || (cluster_offset & 511) != 0) {
ret = -EIO;
@@ -968,15 +968,15 @@ static void qcow_aio_write_cb(void *opaque, int ret)
goto fail;
}
}
- encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf,
+ encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf,
acb->n, 1, &s->aes_encrypt_key);
src_buf = acb->cluster_data;
} else {
src_buf = acb->buf;
}
acb->hd_aiocb = bdrv_aio_write(s->hd,
- (cluster_offset >> 9) + index_in_cluster,
- src_buf, acb->n,
+ (cluster_offset >> 9) + index_in_cluster,
+ src_buf, acb->n,
qcow_aio_write_cb, acb);
if (acb->hd_aiocb == NULL)
goto fail;
@@ -988,13 +988,13 @@ static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
{
BDRVQcowState *s = bs->opaque;
QCowAIOCB *acb;
-
+
s->cluster_cache_offset = -1; /* disable compressed cache */
acb = qcow_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
if (!acb)
return NULL;
-
+
qcow_aio_write_cb(acb, 0);
return &acb->common;
}
@@ -1038,7 +1038,7 @@ static void create_refcount_update(QCowCreateState *s,
start = offset & ~(s->cluster_size - 1);
last = (offset + size - 1) & ~(s->cluster_size - 1);
- for(cluster_offset = start; cluster_offset <= last;
+ for(cluster_offset = start; cluster_offset <= last;
cluster_offset += s->cluster_size) {
p = &s->refcount_block[cluster_offset >> s->cluster_bits];
refcount = be16_to_cpu(*p);
@@ -1054,7 +1054,7 @@ static int qcow_create(const char *filename, int64_t total_size,
QCowHeader header;
uint64_t tmp, offset;
QCowCreateState s1, *s = &s1;
-
+
memset(s, 0, sizeof(*s));
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
@@ -1076,7 +1076,7 @@ static int qcow_create(const char *filename, int64_t total_size,
s->cluster_size = 1 << s->cluster_bits;
header.cluster_bits = cpu_to_be32(s->cluster_bits);
header_size = (header_size + 7) & ~7;
- if (flags) {
+ if (flags & BLOCK_FLAG_ENCRYPT) {
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
} else {
header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
@@ -1096,7 +1096,7 @@ static int qcow_create(const char *filename, int64_t total_size,
s->refcount_block = qemu_mallocz(s->cluster_size);
if (!s->refcount_block)
goto fail;
-
+
s->refcount_table_offset = offset;
header.refcount_table_offset = cpu_to_be64(offset);
header.refcount_table_clusters = cpu_to_be32(1);
@@ -1111,7 +1111,7 @@ static int qcow_create(const char *filename, int64_t total_size,
create_refcount_update(s, s->l1_table_offset, l1_size * sizeof(uint64_t));
create_refcount_update(s, s->refcount_table_offset, s->cluster_size);
create_refcount_update(s, s->refcount_block_offset, s->cluster_size);
-
+
/* write all the data */
write(fd, &header, sizeof(header));
if (backing_file) {
@@ -1124,7 +1124,7 @@ static int qcow_create(const char *filename, int64_t total_size,
}
lseek(fd, s->refcount_table_offset, SEEK_SET);
write(fd, s->refcount_table, s->cluster_size);
-
+
lseek(fd, s->refcount_block_offset, SEEK_SET);
write(fd, s->refcount_block, s->cluster_size);
@@ -1153,7 +1153,7 @@ static int qcow_make_empty(BlockDriverState *bs)
ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
if (ret < 0)
return ret;
-
+
l2_cache_reset(bs);
#endif
return 0;
@@ -1161,7 +1161,7 @@ static int qcow_make_empty(BlockDriverState *bs)
/* XXX: put compressed sectors first, then all the cluster aligned
tables to avoid losing bytes in alignment */
-static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
+static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVQcowState *s = bs->opaque;
@@ -1189,7 +1189,7 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
/* best compression, small window, no zlib header */
memset(&strm, 0, sizeof(strm));
ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,
- Z_DEFLATED, -12,
+ Z_DEFLATED, -12,
9, Z_DEFAULT_STRATEGY);
if (ret != 0) {
qemu_free(out_buf);
@@ -1215,7 +1215,7 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
/* could not compress: write normal cluster */
qcow_write(bs, sector_num, buf, s->cluster_sectors);
} else {
- cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
+ cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
out_len, 0, 0);
cluster_offset &= s->cluster_offset_mask;
if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
@@ -1223,7 +1223,7 @@ static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num,
return -1;
}
}
-
+
qemu_free(out_buf);
return 0;
}
@@ -1238,7 +1238,7 @@ static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{
BDRVQcowState *s = bs->opaque;
bdi->cluster_size = s->cluster_size;
- bdi->vm_state_offset = (int64_t)s->l1_vm_state_index <<
+ bdi->vm_state_offset = (int64_t)s->l1_vm_state_index <<
(s->cluster_bits + s->l2_bits);
return 0;
}
@@ -1247,7 +1247,7 @@ static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
/* snapshot support */
/* update the refcounts of snapshots and the copied flag */
-static int update_snapshot_refcount(BlockDriverState *bs,
+static int update_snapshot_refcount(BlockDriverState *bs,
int64_t l1_table_offset,
int l1_size,
int addend)
@@ -1256,7 +1256,7 @@ static int update_snapshot_refcount(BlockDriverState *bs,
uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated;
int64_t old_offset, old_l2_offset;
int l2_size, i, j, l1_modified, l2_modified, nb_csectors, refcount;
-
+
l2_cache_reset(bs);
l2_table = NULL;
@@ -1268,7 +1268,7 @@ static int update_snapshot_refcount(BlockDriverState *bs,
if (!l1_table)
goto fail;
l1_allocated = 1;
- if (bdrv_pread(s->hd, l1_table_offset,
+ if (bdrv_pread(s->hd, l1_table_offset,
l1_table, l1_size2) != l1_size2)
goto fail;
for(i = 0;i < l1_size; i++)
@@ -1278,7 +1278,7 @@ static int update_snapshot_refcount(BlockDriverState *bs,
l1_table = s->l1_table;
l1_allocated = 0;
}
-
+
l2_size = s->l2_size * sizeof(uint64_t);
l2_table = qemu_malloc(l2_size);
if (!l2_table)
@@ -1298,13 +1298,13 @@ static int update_snapshot_refcount(BlockDriverState *bs,
old_offset = offset;
offset &= ~QCOW_OFLAG_COPIED;
if (offset & QCOW_OFLAG_COMPRESSED) {
- nb_csectors = ((offset >> s->csize_shift) &
+ nb_csectors = ((offset >> s->csize_shift) &
s->csize_mask) + 1;
if (addend != 0)
update_refcount(bs, (offset & s->cluster_offset_mask) & ~511,
nb_csectors * 512, addend);
/* compressed clusters are never modified */
- refcount = 2;
+ refcount = 2;
} else {
if (addend != 0) {
refcount = update_cluster_refcount(bs, offset >> s->cluster_bits, addend);
@@ -1323,7 +1323,7 @@ static int update_snapshot_refcount(BlockDriverState *bs,
}
}
if (l2_modified) {
- if (bdrv_pwrite(s->hd,
+ if (bdrv_pwrite(s->hd,
l2_offset, l2_table, l2_size) != l2_size)
goto fail;
}
@@ -1345,7 +1345,7 @@ static int update_snapshot_refcount(BlockDriverState *bs,
if (l1_modified) {
for(i = 0; i < l1_size; i++)
cpu_to_be64s(&l1_table[i]);
- if (bdrv_pwrite(s->hd, l1_table_offset, l1_table,
+ if (bdrv_pwrite(s->hd, l1_table_offset, l1_table,
l1_size2) != l1_size2)
goto fail;
for(i = 0; i < l1_size; i++)
@@ -1455,7 +1455,7 @@ static int qcow_write_snapshots(BlockDriverState *bs)
snapshots_offset = alloc_clusters(bs, snapshots_size);
offset = snapshots_offset;
-
+
for(i = 0; i < s->nb_snapshots; i++) {
sn = s->snapshots + i;
memset(&h, 0, sizeof(h));
@@ -1465,7 +1465,7 @@ static int qcow_write_snapshots(BlockDriverState *bs)
h.date_sec = cpu_to_be32(sn->date_sec);
h.date_nsec = cpu_to_be32(sn->date_nsec);
h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec);
-
+
id_str_size = strlen(sn->id_str);
name_size = strlen(sn->name);
h.id_str_size = cpu_to_be16(id_str_size);
@@ -1533,7 +1533,7 @@ static int find_snapshot_by_id_or_name(BlockDriverState *bs, const char *name)
{
BDRVQcowState *s = bs->opaque;
int i, ret;
-
+
ret = find_snapshot_by_id(bs, name);
if (ret >= 0)
return ret;
@@ -1545,14 +1545,14 @@ static int find_snapshot_by_id_or_name(BlockDriverState *bs, const char *name)
}
/* if no id is provided, a new one is constructed */
-static int qcow_snapshot_create(BlockDriverState *bs,
+static int qcow_snapshot_create(BlockDriverState *bs,
QEMUSnapshotInfo *sn_info)
{
BDRVQcowState *s = bs->opaque;
QCowSnapshot *snapshots1, sn1, *sn = &sn1;
int i, ret;
uint64_t *l1_table = NULL;
-
+
memset(sn, 0, sizeof(*sn));
if (sn_info->id_str[0] == '\0') {
@@ -1590,7 +1590,7 @@ static int qcow_snapshot_create(BlockDriverState *bs,
l1_table[i] = cpu_to_be64(s->l1_table[i]);
}
if (bdrv_pwrite(s->hd, sn->l1_table_offset,
- l1_table, s->l1_size * sizeof(uint64_t)) !=
+ l1_table, s->l1_size * sizeof(uint64_t)) !=
(s->l1_size * sizeof(uint64_t)))
goto fail;
qemu_free(l1_table);
@@ -1616,7 +1616,7 @@ static int qcow_snapshot_create(BlockDriverState *bs,
}
/* copy the snapshot 'snapshot_name' into the current disk image */
-static int qcow_snapshot_goto(BlockDriverState *bs,
+static int qcow_snapshot_goto(BlockDriverState *bs,
const char *snapshot_id)
{
BDRVQcowState *s = bs->opaque;
@@ -1637,7 +1637,7 @@ static int qcow_snapshot_goto(BlockDriverState *bs,
s->l1_size = sn->l1_size;
l1_size2 = s->l1_size * sizeof(uint64_t);
/* copy the snapshot l1 table to the current l1 table */
- if (bdrv_pread(s->hd, sn->l1_table_offset,
+ if (bdrv_pread(s->hd, sn->l1_table_offset,
s->l1_table, l1_size2) != l1_size2)
goto fail;
if (bdrv_pwrite(s->hd, s->l1_table_offset,
@@ -1663,7 +1663,7 @@ static int qcow_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
BDRVQcowState *s = bs->opaque;
QCowSnapshot *sn;
int snapshot_index, ret;
-
+
snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
if (snapshot_index < 0)
return -ENOENT;
@@ -1693,7 +1693,7 @@ static int qcow_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
return 0;
}
-static int qcow_snapshot_list(BlockDriverState *bs,
+static int qcow_snapshot_list(BlockDriverState *bs,
QEMUSnapshotInfo **psn_tab)
{
BDRVQcowState *s = bs->opaque;
@@ -1731,7 +1731,7 @@ static int refcount_init(BlockDriverState *bs)
{
BDRVQcowState *s = bs->opaque;
int ret, refcount_table_size2, i;
-
+
s->refcount_block_cache = qemu_malloc(s->cluster_size);
if (!s->refcount_block_cache)
goto fail;
@@ -1760,12 +1760,12 @@ static void refcount_close(BlockDriverState *bs)
}
-static int load_refcount_block(BlockDriverState *bs,
+static int load_refcount_block(BlockDriverState *bs,
int64_t refcount_block_offset)
{
BDRVQcowState *s = bs->opaque;
int ret;
- ret = bdrv_pread(s->hd, refcount_block_offset, s->refcount_block_cache,
+ ret = bdrv_pread(s->hd, refcount_block_offset, s->refcount_block_cache,
s->cluster_size);
if (ret != s->cluster_size)
return -EIO;
@@ -1790,7 +1790,7 @@ static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
if (load_refcount_block(bs, refcount_block_offset) < 0)
return 1;
}
- block_index = cluster_index &
+ block_index = cluster_index &
((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
return be16_to_cpu(s->refcount_block_cache[block_index]);
}
@@ -1812,7 +1812,7 @@ static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size)
}
#ifdef DEBUG_ALLOC2
printf("alloc_clusters: size=%lld -> %lld\n",
- size,
+ size,
(s->free_cluster_index - nb_clusters) << s->cluster_bits);
#endif
return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
@@ -1839,13 +1839,13 @@ static int64_t alloc_bytes(BlockDriverState *bs, int size)
BDRVQcowState *s = bs->opaque;
int64_t offset, cluster_offset;
int free_in_cluster;
-
+
assert(size > 0 && size <= s->cluster_size);
if (s->free_byte_offset == 0) {
s->free_byte_offset = alloc_clusters(bs, s->cluster_size);
}
redo:
- free_in_cluster = s->cluster_size -
+ free_in_cluster = s->cluster_size -
(s->free_byte_offset & (s->cluster_size - 1));
if (size <= free_in_cluster) {
/* enough space in current cluster */
@@ -1872,7 +1872,7 @@ static int64_t alloc_bytes(BlockDriverState *bs, int size)
return offset;
}
-static void free_clusters(BlockDriverState *bs,
+static void free_clusters(BlockDriverState *bs,
int64_t offset, int64_t size)
{
update_refcount(bs, offset, size, -1);
@@ -1886,6 +1886,8 @@ static int grow_refcount_table(BlockDriverState *bs, int min_size)
int64_t table_offset;
uint64_t data64;
uint32_t data32;
+ int old_table_size;
+ int64_t old_table_offset;
if (min_size <= s->refcount_table_size)
return 0;
@@ -1910,14 +1912,14 @@ static int grow_refcount_table(BlockDriverState *bs, int min_size)
new_table = qemu_mallocz(new_table_size2);
if (!new_table)
return -ENOMEM;
- memcpy(new_table, s->refcount_table,
+ memcpy(new_table, s->refcount_table,
s->refcount_table_size * sizeof(uint64_t));
for(i = 0; i < s->refcount_table_size; i++)
cpu_to_be64s(&new_table[i]);
/* Note: we cannot update the refcount now to avoid recursion */
table_offset = alloc_clusters_noref(bs, new_table_size2);
ret = bdrv_pwrite(s->hd, table_offset, new_table, new_table_size2);
- if (ret != new_table_size2)
+ if (ret != new_table_size2)
goto fail;
for(i = 0; i < s->refcount_table_size; i++)
be64_to_cpus(&new_table[i]);
@@ -1931,10 +1933,14 @@ static int grow_refcount_table(BlockDriverState *bs, int min_size)
&data32, sizeof(data32)) != sizeof(data32))
goto fail;
qemu_free(s->refcount_table);
+ old_table_offset = s->refcount_table_offset;
+ old_table_size = s->refcount_table_size;
s->refcount_table = new_table;
s->refcount_table_size = new_table_size;
+ s->refcount_table_offset = table_offset;
update_refcount(bs, table_offset, new_table_size2, 1);
+ free_clusters(bs, old_table_offset, old_table_size * sizeof(uint64_t));
return 0;
fail:
free_clusters(bs, table_offset, new_table_size2);
@@ -1944,7 +1950,7 @@ static int grow_refcount_table(BlockDriverState *bs, int min_size)
/* addend must be 1 or -1 */
/* XXX: cache several refcount block clusters ? */
-static int update_cluster_refcount(BlockDriverState *bs,
+static int update_cluster_refcount(BlockDriverState *bs,
int64_t cluster_index,
int addend)
{
@@ -1974,8 +1980,8 @@ static int update_cluster_refcount(BlockDriverState *bs,
return -EINVAL;
s->refcount_table[refcount_table_index] = offset;
data64 = cpu_to_be64(offset);
- ret = bdrv_pwrite(s->hd, s->refcount_table_offset +
- refcount_table_index * sizeof(uint64_t),
+ ret = bdrv_pwrite(s->hd, s->refcount_table_offset +
+ refcount_table_index * sizeof(uint64_t),
&data64, sizeof(data64));
if (ret != sizeof(data64))
return -EINVAL;
@@ -1990,7 +1996,7 @@ static int update_cluster_refcount(BlockDriverState *bs,
}
}
/* we can update the count and save it */
- block_index = cluster_index &
+ block_index = cluster_index &
((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
refcount = be16_to_cpu(s->refcount_block_cache[block_index]);
refcount += addend;
@@ -2000,50 +2006,50 @@ static int update_cluster_refcount(BlockDriverState *bs,
s->free_cluster_index = cluster_index;
}
s->refcount_block_cache[block_index] = cpu_to_be16(refcount);
- if (bdrv_pwrite(s->hd,
- refcount_block_offset + (block_index << REFCOUNT_SHIFT),
+ if (bdrv_pwrite(s->hd,
+ refcount_block_offset + (block_index << REFCOUNT_SHIFT),
&s->refcount_block_cache[block_index], 2) != 2)
return -EIO;
return refcount;
}
-static void update_refcount(BlockDriverState *bs,
- int64_t offset, int64_t length,
+static void update_refcount(BlockDriverState *bs,
+ int64_t offset, int64_t length,
int addend)
{
BDRVQcowState *s = bs->opaque;
int64_t start, last, cluster_offset;
#ifdef DEBUG_ALLOC2
- printf("update_refcount: offset=%lld size=%lld addend=%d\n",
+ printf("update_refcount: offset=%lld size=%lld addend=%d\n",
offset, length, addend);
#endif
if (length <= 0)
return;
start = offset & ~(s->cluster_size - 1);
last = (offset + length - 1) & ~(s->cluster_size - 1);
- for(cluster_offset = start; cluster_offset <= last;
+ for(cluster_offset = start; cluster_offset <= last;
cluster_offset += s->cluster_size) {
update_cluster_refcount(bs, cluster_offset >> s->cluster_bits, addend);
}
}
#ifdef DEBUG_ALLOC
-static void inc_refcounts(BlockDriverState *bs,
- uint16_t *refcount_table,
+static void inc_refcounts(BlockDriverState *bs,
+ uint16_t *refcount_table,
int refcount_table_size,
int64_t offset, int64_t size)
{
BDRVQcowState *s = bs->opaque;
int64_t start, last, cluster_offset;
int k;
-
+
if (size <= 0)
return;
start = offset & ~(s->cluster_size - 1);
last = (offset + size - 1) & ~(s->cluster_size - 1);
- for(cluster_offset = start; cluster_offset <= last;
+ for(cluster_offset = start; cluster_offset <= last;
cluster_offset += s->cluster_size) {
k = cluster_offset >> s->cluster_bits;
if (k < 0 || k >= refcount_table_size) {
@@ -2056,8 +2062,8 @@ static void inc_refcounts(BlockDriverState *bs,
}
}
-static int check_refcounts_l1(BlockDriverState *bs,
- uint16_t *refcount_table,
+static int check_refcounts_l1(BlockDriverState *bs,
+ uint16_t *refcount_table,
int refcount_table_size,
int64_t l1_table_offset, int l1_size,
int check_copied)
@@ -2075,12 +2081,12 @@ static int check_refcounts_l1(BlockDriverState *bs,
l1_table = qemu_malloc(l1_size2);
if (!l1_table)
goto fail;
- if (bdrv_pread(s->hd, l1_table_offset,
+ if (bdrv_pread(s->hd, l1_table_offset,
l1_table, l1_size2) != l1_size2)
goto fail;
for(i = 0;i < l1_size; i++)
be64_to_cpus(&l1_table[i]);
-
+
l2_size = s->l2_size * sizeof(uint64_t);
l2_table = qemu_malloc(l2_size);
if (!l2_table)
@@ -2107,10 +2113,10 @@ static int check_refcounts_l1(BlockDriverState *bs,
offset >> s->cluster_bits);
offset &= ~QCOW_OFLAG_COPIED;
}
- nb_csectors = ((offset >> s->csize_shift) &
+ nb_csectors = ((offset >> s->csize_shift) &
s->csize_mask) + 1;
offset &= s->cluster_offset_mask;
- inc_refcounts(bs, refcount_table,
+ inc_refcounts(bs, refcount_table,
refcount_table_size,
offset & ~511, nb_csectors * 512);
} else {
@@ -2122,13 +2128,13 @@ static int check_refcounts_l1(BlockDriverState *bs,
}
}
offset &= ~QCOW_OFLAG_COPIED;
- inc_refcounts(bs, refcount_table,
+ inc_refcounts(bs, refcount_table,
refcount_table_size,
offset, s->cluster_size);
}
}
}
- inc_refcounts(bs, refcount_table,
+ inc_refcounts(bs, refcount_table,
refcount_table_size,
l2_offset,
s->cluster_size);
@@ -2159,7 +2165,7 @@ static void check_refcounts(BlockDriverState *bs)
/* header */
inc_refcounts(bs, refcount_table, nb_clusters,
0, s->cluster_size);
-
+
check_refcounts_l1(bs, refcount_table, nb_clusters,
s->l1_table_offset, s->l1_size, 1);
@@ -2174,7 +2180,7 @@ static void check_refcounts(BlockDriverState *bs)
/* refcount data */
inc_refcounts(bs, refcount_table, nb_clusters,
- s->refcount_table_offset,
+ s->refcount_table_offset,
s->refcount_table_size * sizeof(uint64_t));
for(i = 0; i < s->refcount_table_size; i++) {
int64_t offset;
diff --git a/block-raw.c b/block-raw.c
index 29882e1f7..2f2e19f9b 100644
--- a/block-raw.c
+++ b/block-raw.c
@@ -1,8 +1,8 @@
/*
* Block driver for RAW files
- *
+ *
* Copyright (c) 2006 Fabrice Bellard
- *
+ *
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
@@ -59,6 +59,14 @@
//#define DEBUG_FLOPPY
+#define DEBUG_BLOCK
+#if defined(DEBUG_BLOCK) && !defined(QEMU_TOOL)
+#define DEBUG_BLOCK_PRINT(formatCstr, args...) do { if (loglevel != 0) \
+ { fprintf(logfile, formatCstr, ##args); fflush(logfile); } } while (0)
+#else
+#define DEBUG_BLOCK_PRINT(formatCstr, args...)
+#endif
+
#define FTYPE_FILE 0
#define FTYPE_CD 1
#define FTYPE_FD 2
@@ -70,6 +78,7 @@
typedef struct BDRVRawState {
int fd;
int type;
+ unsigned int lseek_err_cnt;
#if defined(__linux__)
/* linux floppy specific */
int fd_open_flags;
@@ -87,6 +96,8 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
BDRVRawState *s = bs->opaque;
int fd, open_flags, ret;
+ s->lseek_err_cnt = 0;
+
open_flags = O_BINARY;
if ((flags & BDRV_O_ACCESS) == O_RDWR) {
open_flags |= O_RDWR;
@@ -127,33 +138,92 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
#endif
*/
-static int raw_pread(BlockDriverState *bs, int64_t offset,
+static int raw_pread(BlockDriverState *bs, int64_t offset,
uint8_t *buf, int count)
{
BDRVRawState *s = bs->opaque;
int ret;
-
+
ret = fd_open(bs);
if (ret < 0)
return ret;
- lseek(s->fd, offset, SEEK_SET);
+ if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
+ ++(s->lseek_err_cnt);
+ if(s->lseek_err_cnt <= 10) {
+ DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
+ "] lseek failed : %d = %s\n",
+ s->fd, bs->filename, offset, buf, count,
+ bs->total_sectors, errno, strerror(errno));
+ }
+ return -1;
+ }
+ s->lseek_err_cnt=0;
+
ret = read(s->fd, buf, count);
+ if (ret == count)
+ goto label__raw_read__success;
+
+ DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
+ "] read failed %d : %d = %s\n",
+ s->fd, bs->filename, offset, buf, count,
+ bs->total_sectors, ret, errno, strerror(errno));
+
+ /* Try harder for CDrom. */
+ if (bs->type == BDRV_TYPE_CDROM) {
+ lseek(s->fd, offset, SEEK_SET);
+ ret = read(s->fd, buf, count);
+ if (ret == count)
+ goto label__raw_read__success;
+ lseek(s->fd, offset, SEEK_SET);
+ ret = read(s->fd, buf, count);
+ if (ret == count)
+ goto label__raw_read__success;
+
+ DEBUG_BLOCK_PRINT("raw_pread(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
+ "] retry read failed %d : %d = %s\n",
+ s->fd, bs->filename, offset, buf, count,
+ bs->total_sectors, ret, errno, strerror(errno));
+ }
+
+label__raw_read__success:
+
return ret;
}
-static int raw_pwrite(BlockDriverState *bs, int64_t offset,
+static int raw_pwrite(BlockDriverState *bs, int64_t offset,
const uint8_t *buf, int count)
{
BDRVRawState *s = bs->opaque;
int ret;
-
+
ret = fd_open(bs);
if (ret < 0)
return ret;
- lseek(s->fd, offset, SEEK_SET);
+ if (lseek(s->fd, offset, SEEK_SET) == (off_t)-1) {
+ ++(s->lseek_err_cnt);
+ if(s->lseek_err_cnt) {
+ DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%"
+ PRId64 "] lseek failed : %d = %s\n",
+ s->fd, bs->filename, offset, buf, count,
+ bs->total_sectors, errno, strerror(errno));
+ }
+ return -1;
+ }
+ s->lseek_err_cnt = 0;
+
ret = write(s->fd, buf, count);
+ if (ret == count)
+ goto label__raw_write__success;
+
+ DEBUG_BLOCK_PRINT("raw_pwrite(%d:%s, %" PRId64 ", %p, %d) [%" PRId64
+ "] write failed %d : %d = %s\n",
+ s->fd, bs->filename, offset, buf, count,
+ bs->total_sectors, ret, errno, strerror(errno));
+
+label__raw_write__success:
+
return ret;
}
@@ -191,7 +261,7 @@ void qemu_aio_init(void)
struct sigaction act;
aio_initialized = 1;
-
+
sigfillset(&act.sa_mask);
act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
act.sa_handler = aio_signal_handler;
@@ -333,7 +403,7 @@ static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
if (aio_read(&acb->aiocb) < 0) {
qemu_aio_release(acb);
return NULL;
- }
+ }
return &acb->common;
}
@@ -349,7 +419,7 @@ static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
if (aio_write(&acb->aiocb) < 0) {
qemu_aio_release(acb);
return NULL;
- }
+ }
return &acb->common;
}
@@ -454,7 +524,7 @@ static int raw_create(const char *filename, int64_t total_size,
if (flags || backing_file)
return -ENOTSUP;
- fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
if (fd < 0)
return -EIO;
@@ -479,7 +549,7 @@ BlockDriver bdrv_raw = {
raw_close,
raw_create,
raw_flush,
-
+
.bdrv_aio_read = raw_aio_read,
.bdrv_aio_write = raw_aio_write,
.bdrv_aio_cancel = raw_aio_cancel,
@@ -500,7 +570,7 @@ static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFI
kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
{
- kern_return_t kernResult;
+ kern_return_t kernResult;
mach_port_t masterPort;
CFMutableDictionaryRef classesToMatch;
@@ -508,8 +578,8 @@ kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
if ( KERN_SUCCESS != kernResult ) {
printf( "IOMasterPort returned %d\n", kernResult );
}
-
- classesToMatch = IOServiceMatching( kIOCDMediaClass );
+
+ classesToMatch = IOServiceMatching( kIOCDMediaClass );
if ( classesToMatch == NULL ) {
printf( "IOServiceMatching returned a NULL dictionary.\n" );
} else {
@@ -520,7 +590,7 @@ kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
{
printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
}
-
+
return kernResult;
}
@@ -546,7 +616,7 @@ kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex ma
}
IOObjectRelease( nextMedia );
}
-
+
return kernResult;
}
@@ -563,10 +633,10 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
io_iterator_t mediaIterator;
char bsdPath[ MAXPATHLEN ];
int fd;
-
+
kernResult = FindEjectableCDMedia( &mediaIterator );
kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
-
+
if ( bsdPath[ 0 ] != '\0' ) {
strcat(bsdPath,"s0");
/* some CDs don't have a partition 0 */
@@ -578,7 +648,7 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
}
filename = bsdPath;
}
-
+
if ( mediaIterator )
IOObjectRelease( mediaIterator );
}
@@ -636,7 +706,7 @@ static int fd_open(BlockDriverState *bs)
if (s->type != FTYPE_FD)
return 0;
last_media_present = (s->fd >= 0);
- if (s->fd >= 0 &&
+ if (s->fd >= 0 &&
(qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
close(s->fd);
s->fd = -1;
@@ -645,7 +715,7 @@ static int fd_open(BlockDriverState *bs)
#endif
}
if (s->fd < 0) {
- if (s->fd_got_error &&
+ if (s->fd_got_error &&
(qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
#ifdef DEBUG_FLOPPY
printf("No floppy (open delayed)\n");
@@ -815,7 +885,7 @@ BlockDriver bdrv_host_device = {
raw_close,
NULL,
raw_flush,
-
+
.bdrv_aio_read = raw_aio_read,
.bdrv_aio_write = raw_aio_write,
.bdrv_aio_cancel = raw_aio_cancel,
@@ -911,7 +981,7 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
#else
overlapped = FILE_FLAG_OVERLAPPED;
#endif
- s->hfile = CreateFile(filename, access_flags,
+ s->hfile = CreateFile(filename, access_flags,
FILE_SHARE_READ, NULL,
create_flags, overlapped, NULL);
if (s->hfile == INVALID_HANDLE_VALUE) {
@@ -924,14 +994,14 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
return 0;
}
-static int raw_pread(BlockDriverState *bs, int64_t offset,
+static int raw_pread(BlockDriverState *bs, int64_t offset,
uint8_t *buf, int count)
{
BDRVRawState *s = bs->opaque;
OVERLAPPED ov;
DWORD ret_count;
int ret;
-
+
memset(&ov, 0, sizeof(ov));
ov.Offset = offset;
ov.OffsetHigh = offset >> 32;
@@ -946,14 +1016,14 @@ static int raw_pread(BlockDriverState *bs, int64_t offset,
return ret_count;
}
-static int raw_pwrite(BlockDriverState *bs, int64_t offset,
+static int raw_pwrite(BlockDriverState *bs, int64_t offset,
const uint8_t *buf, int count)
{
BDRVRawState *s = bs->opaque;
OVERLAPPED ov;
DWORD ret_count;
int ret;
-
+
memset(&ov, 0, sizeof(ov));
ov.Offset = offset;
ov.OffsetHigh = offset >> 32;
@@ -1103,7 +1173,7 @@ static int64_t raw_getlength(BlockDriverState *bs)
{
BDRVRawState *s = bs->opaque;
LARGE_INTEGER l;
- ULARGE_INTEGER available, total, total_free;
+ ULARGE_INTEGER available, total, total_free;
DISK_GEOMETRY dg;
DWORD count;
BOOL status;
@@ -1141,7 +1211,7 @@ static int raw_create(const char *filename, int64_t total_size,
if (flags || backing_file)
return -ENOTSUP;
- fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
0644);
if (fd < 0)
return -EIO;
@@ -1188,7 +1258,7 @@ BlockDriver bdrv_raw = {
raw_close,
raw_create,
raw_flush,
-
+
#if 0
.bdrv_aio_read = raw_aio_read,
.bdrv_aio_write = raw_aio_write,
@@ -1267,7 +1337,7 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
}
}
s->type = find_device_type(bs, filename);
-
+
if ((flags & BDRV_O_ACCESS) == O_RDWR) {
access_flags = GENERIC_READ | GENERIC_WRITE;
} else {
@@ -1280,7 +1350,7 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
#else
overlapped = FILE_FLAG_OVERLAPPED;
#endif
- s->hfile = CreateFile(filename, access_flags,
+ s->hfile = CreateFile(filename, access_flags,
FILE_SHARE_READ, NULL,
create_flags, overlapped, NULL);
if (s->hfile == INVALID_HANDLE_VALUE) {
@@ -1295,7 +1365,7 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
#if 0
/***********************************************/
-/* removable device additionnal commands */
+/* removable device additional commands */
static int raw_is_inserted(BlockDriverState *bs)
{
@@ -1314,10 +1384,10 @@ static int raw_eject(BlockDriverState *bs, int eject_flag)
if (s->type == FTYPE_FILE)
return -ENOTSUP;
if (eject_flag) {
- DeviceIoControl(s->hfile, IOCTL_STORAGE_EJECT_MEDIA,
+ DeviceIoControl(s->hfile, IOCTL_STORAGE_EJECT_MEDIA,
NULL, 0, NULL, 0, &lpBytesReturned, NULL);
} else {
- DeviceIoControl(s->hfile, IOCTL_STORAGE_LOAD_MEDIA,
+ DeviceIoControl(s->hfile, IOCTL_STORAGE_LOAD_MEDIA,
NULL, 0, NULL, 0, &lpBytesReturned, NULL);
}
}
@@ -1338,7 +1408,7 @@ BlockDriver bdrv_host_device = {
raw_close,
NULL,
raw_flush,
-
+
#if 0
.bdrv_aio_read = raw_aio_read,
.bdrv_aio_write = raw_aio_write,
diff --git a/block-vmdk.c b/block-vmdk.c
index 28df8ae46..ad2270034 100644
--- a/block-vmdk.c
+++ b/block-vmdk.c
@@ -1,9 +1,9 @@
/*
* Block driver for the VMDK format
- *
+ *
* Copyright (c) 2004 Fabrice Bellard
* Copyright (c) 2005 Filip Navara
- *
+ *
* 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
@@ -75,8 +75,25 @@ typedef struct BDRVVmdkState {
unsigned int cluster_sectors;
uint32_t parent_cid;
+ int is_parent;
} BDRVVmdkState;
+typedef struct VmdkMetaData {
+ uint32_t offset;
+ unsigned int l1_index;
+ unsigned int l2_index;
+ unsigned int l2_offset;
+ int valid;
+} VmdkMetaData;
+
+typedef struct ActiveBDRVState{
+ BlockDriverState *hd; // active image handler
+ uint64_t cluster_offset; // current write offset
+}ActiveBDRVState;
+
+static ActiveBDRVState activeBDRV;
+
+
static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
{
uint32_t magic;
@@ -93,16 +110,16 @@ static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
#define CHECK_CID 1
-#define SECTOR_SIZE 512
+#define SECTOR_SIZE 512
#define DESC_SIZE 20*SECTOR_SIZE // 20 sectors of 512 bytes each
-#define HEADER_SIZE 512 // first sector of 512 bytes
+#define HEADER_SIZE 512 // first sector of 512 bytes
static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
{
BDRVVmdkState *s = bs->opaque;
char desc[DESC_SIZE];
uint32_t cid;
- char *p_name, *cid_str;
+ char *p_name, *cid_str;
size_t cid_str_size;
/* the descriptor offset = 0x200 */
@@ -170,7 +187,7 @@ static int vmdk_snapshot_create(const char *filename, const char *backing_file)
{
int snp_fd, p_fd;
uint32_t p_cid;
- char *p_name, *gd_buf, *rgd_buf;
+ char *p_name, *gd_buf, *rgd_buf;
const char *real_filename, *temp_str;
VMDK4Header header;
uint32_t gde_entries, gd_size;
@@ -254,7 +271,7 @@ static int vmdk_snapshot_create(const char *filename, const char *backing_file)
gt_size = (int64_t)header.num_gtes_per_gte * header.granularity * SECTOR_SIZE;
if (!gt_size)
goto fail;
- gde_entries = (uint32_t)(capacity / gt_size); // number of gde/rgde
+ gde_entries = (uint32_t)(capacity / gt_size); // number of gde/rgde
gd_size = gde_entries * sizeof(uint32_t);
/* write RGD */
@@ -291,7 +308,7 @@ static int vmdk_snapshot_create(const char *filename, const char *backing_file)
fail_gd:
qemu_free(gd_buf);
- fail_rgd:
+ fail_rgd:
qemu_free(rgd_buf);
fail:
close(p_fd);
@@ -305,11 +322,11 @@ static void vmdk_parent_close(BlockDriverState *bs)
bdrv_close(bs->backing_hd);
}
-
+int parent_open = 0;
static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
{
BDRVVmdkState *s = bs->opaque;
- char *p_name;
+ char *p_name;
char desc[DESC_SIZE];
char parent_img_name[1024];
@@ -324,7 +341,7 @@ static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
p_name += sizeof("parentFileNameHint") + 1;
if ((end_name = strchr(p_name,'\"')) == 0)
return -1;
-
+
strncpy(s->hd->backing_file, p_name, end_name - p_name);
if (stat(s->hd->backing_file, &file_buf) != 0) {
path_combine(parent_img_name, sizeof(parent_img_name),
@@ -339,8 +356,10 @@ static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
bdrv_close(s->hd);
return -1;
}
- if (bdrv_open(s->hd->backing_hd, parent_img_name, 0) < 0)
+ parent_open = 1;
+ if (bdrv_open(s->hd->backing_hd, parent_img_name, BDRV_O_RDONLY) < 0)
goto failure;
+ parent_open = 0;
}
return 0;
@@ -352,6 +371,11 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
uint32_t magic;
int l1_size, i, ret;
+ if (parent_open)
+ // Parent must be opened as RO.
+ flags = BDRV_O_RDONLY;
+ fprintf(stderr, "(VMDK) image open: flags=0x%x filename=%s\n", flags, bs->filename);
+
ret = bdrv_file_open(&s->hd, filename, flags);
if (ret < 0)
return ret;
@@ -382,11 +406,16 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
if (s->l1_entry_sectors <= 0)
goto fail;
- s->l1_size = (bs->total_sectors + s->l1_entry_sectors - 1)
+ s->l1_size = (bs->total_sectors + s->l1_entry_sectors - 1)
/ s->l1_entry_sectors;
s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;
+ if (parent_open)
+ s->is_parent = 1;
+ else
+ s->is_parent = 0;
+
// try to open parent images, if exist
if (vmdk_parent_open(bs, filename) != 0)
goto fail;
@@ -430,7 +459,8 @@ static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
return -1;
}
-static uint64_t get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate);
+static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
+ uint64_t offset, int allocate);
static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
uint64_t offset, int allocate)
@@ -446,27 +476,54 @@ static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
if (!vmdk_is_cid_valid(bs))
return -1;
- parent_cluster_offset = get_cluster_offset(s->hd->backing_hd, offset, allocate);
- if (bdrv_pread(ps->hd, parent_cluster_offset, whole_grain, ps->cluster_sectors*512) !=
- ps->cluster_sectors*512)
- return -1;
- if (bdrv_pwrite(s->hd, cluster_offset << 9, whole_grain, sizeof(whole_grain)) !=
- sizeof(whole_grain))
+ parent_cluster_offset = get_cluster_offset(s->hd->backing_hd, NULL, offset, allocate);
+
+ if (parent_cluster_offset) {
+ BDRVVmdkState *act_s = activeBDRV.hd->opaque;
+
+ if (bdrv_pread(ps->hd, parent_cluster_offset, whole_grain, ps->cluster_sectors*512) != ps->cluster_sectors*512)
+ return -1;
+
+ //Write grain only into the active image
+ if (bdrv_pwrite(act_s->hd, activeBDRV.cluster_offset << 9, whole_grain, sizeof(whole_grain)) != sizeof(whole_grain))
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int vmdk_L2update(BlockDriverState *bs, VmdkMetaData *m_data)
+{
+ BDRVVmdkState *s = bs->opaque;
+
+ /* update L2 table */
+ if (bdrv_pwrite(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
+ &(m_data->offset), sizeof(m_data->offset)) != sizeof(m_data->offset))
+ return -1;
+ /* update backup L2 table */
+ if (s->l1_backup_table_offset != 0) {
+ m_data->l2_offset = s->l1_backup_table[m_data->l1_index];
+ if (bdrv_pwrite(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
+ &(m_data->offset), sizeof(m_data->offset)) != sizeof(m_data->offset))
return -1;
}
+
return 0;
}
-static uint64_t get_cluster_offset(BlockDriverState *bs,
+static uint64_t get_cluster_offset(BlockDriverState *bs, VmdkMetaData *m_data,
uint64_t offset, int allocate)
{
BDRVVmdkState *s = bs->opaque;
unsigned int l1_index, l2_offset, l2_index;
int min_index, i, j;
- uint32_t min_count, *l2_table, tmp;
+ uint32_t min_count, *l2_table, tmp = 0;
uint64_t cluster_offset;
-
+
+ if (m_data)
+ m_data->valid = 0;
+
l1_index = (offset >> 9) / s->l1_entry_sectors;
if (l1_index >= s->l1_size)
return 0;
@@ -495,7 +552,7 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
}
}
l2_table = s->l2_cache + (min_index * s->l2_size);
- if (bdrv_pread(s->hd, (int64_t)l2_offset * 512, l2_table, s->l2_size * sizeof(uint32_t)) !=
+ if (bdrv_pread(s->hd, (int64_t)l2_offset * 512, l2_table, s->l2_size * sizeof(uint32_t)) !=
s->l2_size * sizeof(uint32_t))
return 0;
@@ -504,45 +561,50 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
found:
l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size;
cluster_offset = le32_to_cpu(l2_table[l2_index]);
- if (!cluster_offset) {
- struct stat file_buf;
+ if (!cluster_offset) {
if (!allocate)
return 0;
- stat(s->hd->filename, &file_buf);
- cluster_offset = file_buf.st_size;
- bdrv_truncate(s->hd, cluster_offset + (s->cluster_sectors << 9));
-
- cluster_offset >>= 9;
- /* update L2 table */
- tmp = cpu_to_le32(cluster_offset);
- l2_table[l2_index] = tmp;
- if (bdrv_pwrite(s->hd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)),
- &tmp, sizeof(tmp)) != sizeof(tmp))
- return 0;
- /* update backup L2 table */
- if (s->l1_backup_table_offset != 0) {
- l2_offset = s->l1_backup_table[l1_index];
- if (bdrv_pwrite(s->hd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)),
- &tmp, sizeof(tmp)) != sizeof(tmp))
- return 0;
+ // Avoid the L2 tables update for the images that have snapshots.
+ if (!s->is_parent) {
+ cluster_offset = bdrv_getlength(s->hd);
+ bdrv_truncate(s->hd, cluster_offset + (s->cluster_sectors << 9));
+
+ cluster_offset >>= 9;
+ tmp = cpu_to_le32(cluster_offset);
+ l2_table[l2_index] = tmp;
+ // Save the active image state
+ activeBDRV.cluster_offset = cluster_offset;
+ activeBDRV.hd = bs;
}
-
+ /* First of all we write grain itself, to avoid race condition
+ * that may to corrupt the image.
+ * This problem may occur because of insufficient space on host disk
+ * or inappropriate VM shutdown.
+ */
if (get_whole_cluster(bs, cluster_offset, offset, allocate) == -1)
return 0;
+
+ if (m_data) {
+ m_data->offset = tmp;
+ m_data->l1_index = l1_index;
+ m_data->l2_index = l2_index;
+ m_data->l2_offset = l2_offset;
+ m_data->valid = 1;
+ }
}
cluster_offset <<= 9;
return cluster_offset;
}
-static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
+static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
BDRVVmdkState *s = bs->opaque;
int index_in_cluster, n;
uint64_t cluster_offset;
- cluster_offset = get_cluster_offset(bs, sector_num << 9, 0);
+ cluster_offset = get_cluster_offset(bs, NULL, sector_num << 9, 0);
index_in_cluster = sector_num % s->cluster_sectors;
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
@@ -551,7 +613,7 @@ static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
return (cluster_offset != 0);
}
-static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
+static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVVmdkState *s = bs->opaque;
@@ -559,7 +621,7 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
uint64_t cluster_offset;
while (nb_sectors > 0) {
- cluster_offset = get_cluster_offset(bs, sector_num << 9, 0);
+ cluster_offset = get_cluster_offset(bs, NULL, sector_num << 9, 0);
index_in_cluster = sector_num % s->cluster_sectors;
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
@@ -586,24 +648,39 @@ static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
return 0;
}
-static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
+static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BDRVVmdkState *s = bs->opaque;
+ VmdkMetaData m_data;
int index_in_cluster, n;
uint64_t cluster_offset;
static int cid_update = 0;
+ if (sector_num > bs->total_sectors) {
+ fprintf(stderr,
+ "(VMDK) Wrong offset: sector_num=0x%" PRIx64
+ " total_sectors=0x%" PRIx64 "\n",
+ sector_num, bs->total_sectors);
+ return -1;
+ }
+
while (nb_sectors > 0) {
index_in_cluster = sector_num & (s->cluster_sectors - 1);
n = s->cluster_sectors - index_in_cluster;
if (n > nb_sectors)
n = nb_sectors;
- cluster_offset = get_cluster_offset(bs, sector_num << 9, 1);
+ cluster_offset = get_cluster_offset(bs, &m_data, sector_num << 9, 1);
if (!cluster_offset)
return -1;
+
if (bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
return -1;
+ if (m_data.valid) {
+ /* update L2 tables */
+ if (vmdk_L2update(bs, &m_data) == -1)
+ return -1;
+ }
nb_sectors -= n;
sector_num += n;
buf += n * 512;
@@ -636,7 +713,7 @@ static int vmdk_create(const char *filename, int64_t total_size,
"# The Disk Data Base \n"
"#DDB\n"
"\n"
- "ddb.virtualHWVersion = \"4\"\n"
+ "ddb.virtualHWVersion = \"%d\"\n"
"ddb.geometry.cylinders = \"%lu\"\n"
"ddb.geometry.heads = \"16\"\n"
"ddb.geometry.sectors = \"63\"\n"
@@ -685,8 +762,8 @@ static int vmdk_create(const char *filename, int64_t total_size,
header.check_bytes[1] = 0x20;
header.check_bytes[2] = 0xd;
header.check_bytes[3] = 0xa;
-
- /* write all the data */
+
+ /* write all the data */
write(fd, &magic, sizeof(magic));
write(fd, &header, sizeof(header));
@@ -697,7 +774,7 @@ static int vmdk_create(const char *filename, int64_t total_size,
for (i = 0, tmp = header.rgd_offset + gd_size;
i < gt_count; i++, tmp += gt_size)
write(fd, &tmp, sizeof(tmp));
-
+
/* write backup grain directory */
lseek(fd, le64_to_cpu(header.gd_offset) << 9, SEEK_SET);
for (i = 0, tmp = header.gd_offset + gd_size;
@@ -713,7 +790,7 @@ static int vmdk_create(const char *filename, int64_t total_size,
if ((temp_str = strrchr(real_filename, ':')) != NULL)
real_filename = temp_str + 1;
sprintf(desc, desc_template, time(NULL), (unsigned long)total_size,
- real_filename, total_size / (63 * 16));
+ real_filename, (flags & BLOCK_FLAG_COMPAT6 ? 6 : 4), total_size / (63 * 16));
/* write the descriptor */
lseek(fd, le64_to_cpu(header.desc_offset) << 9, SEEK_SET);
diff --git a/block-vpc.c b/block-vpc.c
index 4d228c5b6..be74c290d 100644
--- a/block-vpc.c
+++ b/block-vpc.c
@@ -1,8 +1,8 @@
/*
* Block driver for Conectix/Microsoft Virtual PC images
- *
+ *
* Copyright (c) 2005 Alex Beregszaszi
- *
+ *
* 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
@@ -65,7 +65,7 @@ struct vpc_subheader {
typedef struct BDRVVPCState {
int fd;
-
+
int pagetable_entries;
uint32_t *pagetable;
@@ -74,7 +74,7 @@ typedef struct BDRVVPCState {
uint8_t *pageentry_u8;
uint32_t *pageentry_u32;
uint16_t *pageentry_u16;
-
+
uint64_t last_bitmap;
#endif
} BDRVVPCState;
@@ -97,7 +97,7 @@ static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
return -1;
bs->read_only = 1; // no write support yet
-
+
s->fd = fd;
if (read(fd, &header, HEADER_SIZE) != HEADER_SIZE)
@@ -153,13 +153,13 @@ static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
pagetable_index = offset / s->pageentry_size;
pageentry_index = (offset % s->pageentry_size) / 512;
-
+
if (pagetable_index > s->pagetable_entries || s->pagetable[pagetable_index] == 0xffffffff)
return -1; // not allocated
bitmap_offset = 512 * s->pagetable[pagetable_index];
block_offset = bitmap_offset + 512 + (512 * pageentry_index);
-
+
// printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",
// sector_num, pagetable_index, pageentry_index,
// bitmap_offset, block_offset);
@@ -172,7 +172,7 @@ static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
lseek(s->fd, bitmap_offset, SEEK_SET);
s->last_bitmap = bitmap_offset;
-
+
// Scary! Bitmap is stored as big endian 32bit entries,
// while we used to look it up byte by byte
read(s->fd, s->pageentry_u8, 512);
@@ -184,7 +184,7 @@ static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
return -1;
#else
lseek(s->fd, bitmap_offset + (pageentry_index / 8), SEEK_SET);
-
+
read(s->fd, &bitmap_entry, 1);
if ((bitmap_entry >> (pageentry_index % 8)) & 1)
@@ -196,7 +196,7 @@ static inline int seek_to_sector(BlockDriverState *bs, int64_t sector_num)
return 0;
}
-static int vpc_read(BlockDriverState *bs, int64_t sector_num,
+static int vpc_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVVPCState *s = bs->opaque;
diff --git a/block-vvfat.c b/block-vvfat.c
index 48a52e311..3237c266c 100644
--- a/block-vvfat.c
+++ b/block-vvfat.c
@@ -1,9 +1,9 @@
/* vim:set shiftwidth=4 ts=8: */
/*
* QEMU Block driver for virtual VFAT (shadows a local directory)
- *
+ *
* Copyright (c) 2004,2005 Johannes E. Schindelin
- *
+ *
* 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
@@ -38,7 +38,7 @@
/* TODO: add ":bootsector=blabla.img:" */
/* LATER TODO: add automatic boot sector generation from
BOOTEASY.ASM and Ranish Partition Manager
- Note that DOS assumes the system files to be the first files in the
+ Note that DOS assumes the system files to be the first files in the
file system (test if the boot sector still relies on that fact)! */
/* MAYBE TODO: write block-visofs.c */
/* TODO: call try_commit() only after a timeout */
@@ -153,7 +153,7 @@ static inline int array_roll(array_t* array,int index_to,int index_from,int coun
index_to<0 || index_to>=array->next ||
index_from<0 || index_from>=array->next)
return -1;
-
+
if(index_to==index_from)
return 0;
@@ -167,7 +167,7 @@ static inline int array_roll(array_t* array,int index_to,int index_from,int coun
memmove(to+is*count,to,from-to);
else
memmove(from,from+is*count,to-from);
-
+
memcpy(to,buf,is*count);
free(buf);
@@ -242,21 +242,25 @@ typedef struct bootsector_t {
uint8_t magic[2];
} __attribute__((packed)) bootsector_t;
+typedef struct {
+ uint8_t head;
+ uint8_t sector;
+ uint8_t cylinder;
+} mbr_chs_t;
+
typedef struct partition_t {
uint8_t attributes; /* 0x80 = bootable */
- uint8_t start_head;
- uint8_t start_sector;
- uint8_t start_cylinder;
- uint8_t fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xb = FAT32 */
- uint8_t end_head;
- uint8_t end_sector;
- uint8_t end_cylinder;
+ mbr_chs_t start_CHS;
+ uint8_t fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */
+ mbr_chs_t end_CHS;
uint32_t start_sector_long;
- uint32_t end_sector_long;
+ uint32_t length_sector_long;
} __attribute__((packed)) partition_t;
typedef struct mbr_t {
- uint8_t ignored[0x1be];
+ uint8_t ignored[0x1b8];
+ uint32_t nt_id;
+ uint8_t ignored2[2];
partition_t partition[4];
uint8_t magic[2];
} __attribute__((packed)) mbr_t;
@@ -319,10 +323,10 @@ typedef struct BDRVVVFATState {
BlockDriverState* bs; /* pointer to parent */
unsigned int first_sectors_number; /* 1 for a single partition, 0x40 for a disk with partition table */
unsigned char first_sectors[0x40*0x200];
-
+
int fat_type; /* 16 or 32 */
array_t fat,directory,mapping;
-
+
unsigned int cluster_size;
unsigned int sectors_per_cluster;
unsigned int sectors_per_fat;
@@ -332,7 +336,7 @@ typedef struct BDRVVVFATState {
uint32_t sector_count; /* total number of sectors of the partition */
uint32_t cluster_count; /* total number of clusters of this partition */
uint32_t max_fat_value;
-
+
int current_fd;
mapping_t* current_mapping;
unsigned char* cluster; /* points to current cluster */
@@ -350,26 +354,57 @@ typedef struct BDRVVVFATState {
int downcase_short_names;
} BDRVVVFATState;
+/* take the sector position spos and convert it to Cylinder/Head/Sector position
+ * if the position is outside the specified geometry, fill maximum value for CHS
+ * and return 1 to signal overflow.
+ */
+static int sector2CHS(BlockDriverState* bs, mbr_chs_t * chs, int spos){
+ int head,sector;
+ sector = spos % (bs->secs); spos/= bs->secs;
+ head = spos % (bs->heads); spos/= bs->heads;
+ if(spos >= bs->cyls){
+ /* Overflow,
+ it happens if 32bit sector positions are used, while CHS is only 24bit.
+ Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */
+ chs->head = 0xFF;
+ chs->sector = 0xFF;
+ chs->cylinder = 0xFF;
+ return 1;
+ }
+ chs->head = (uint8_t)head;
+ chs->sector = (uint8_t)( (sector+1) | ((spos>>8)<<6) );
+ chs->cylinder = (uint8_t)spos;
+ return 0;
+}
static void init_mbr(BDRVVVFATState* s)
{
/* TODO: if the files mbr.img and bootsect.img exist, use them */
mbr_t* real_mbr=(mbr_t*)s->first_sectors;
partition_t* partition=&(real_mbr->partition[0]);
+ int lba;
memset(s->first_sectors,0,512);
-
+
+ /* Win NT Disk Signature */
+ real_mbr->nt_id= cpu_to_le32(0xbe1afdfa);
+
partition->attributes=0x80; /* bootable */
- partition->start_head=1;
- partition->start_sector=1;
- partition->start_cylinder=0;
+
+ /* LBA is used when partition is outside the CHS geometry */
+ lba = sector2CHS(s->bs, &partition->start_CHS, s->first_sectors_number-1);
+ lba|= sector2CHS(s->bs, &partition->end_CHS, s->sector_count);
+
+ /*LBA partitions are identified only by start/length_sector_long not by CHS*/
+ partition->start_sector_long =cpu_to_le32(s->first_sectors_number-1);
+ partition->length_sector_long=cpu_to_le32(s->sector_count - s->first_sectors_number+1);
+
/* FAT12/FAT16/FAT32 */
- partition->fs_type=(s->fat_type==12?0x1:s->fat_type==16?0x6:0xb);
- partition->end_head=s->bs->heads-1;
- partition->end_sector=0xff; /* end sector & upper 2 bits of cylinder */;
- partition->end_cylinder=0xff; /* lower 8 bits of end cylinder */;
- partition->start_sector_long=cpu_to_le32(s->bs->secs);
- partition->end_sector_long=cpu_to_le32(s->sector_count);
+ /* DOS uses different types when partition is LBA,
+ probably to prevent older versions from using CHS on them */
+ partition->fs_type= s->fat_type==12 ? 0x1:
+ s->fat_type==16 ? (lba?0xe:0x06):
+ /*fat_tyoe==32*/ (lba?0xc:0x0b);
real_mbr->magic[0]=0x55; real_mbr->magic[1]=0xaa;
}
@@ -478,7 +513,7 @@ static inline uint8_t fat_chksum(const direntry_t* entry)
for(i=0;i<11;i++)
chksum=(((chksum&0xfe)>>1)|((chksum&0x01)?0x80:0))
+(unsigned char)entry->name[i];
-
+
return chksum;
}
@@ -554,7 +589,7 @@ static inline void init_fat(BDRVVVFATState* s)
s->sectors_per_fat * 0x200 / s->fat.item_size - 1);
}
memset(s->fat.pointer,0,s->fat.size);
-
+
switch(s->fat_type) {
case 12: s->max_fat_value=0xfff; break;
case 16: s->max_fat_value=0xffff; break;
@@ -579,10 +614,10 @@ static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
memcpy(entry->name,filename,strlen(filename));
return entry;
}
-
+
entry_long=create_long_filename(s,filename);
-
- i = strlen(filename);
+
+ i = strlen(filename);
for(j = i - 1; j>0 && filename[j]!='.';j--);
if (j > 0)
i = (j > 8 ? 8 : j);
@@ -592,7 +627,7 @@ static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
entry=array_get_next(&(s->directory));
memset(entry->name,0x20,11);
strncpy(entry->name,filename,i);
-
+
if(j > 0)
for (i = 0; i < 3 && filename[j+1+i]; i++)
entry->extension[i] = filename[j+1+i];
@@ -618,7 +653,7 @@ static inline direntry_t* create_short_and_long_name(BDRVVVFATState* s,
if(entry1==entry) /* no dupe found */
break;
- /* use all 8 characters of name */
+ /* use all 8 characters of name */
if(entry->name[7]==' ') {
int j;
for(j=6;j>0 && entry->name[j]==' ';j--)
@@ -675,11 +710,11 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
mapping->end = mapping->begin;
return -1;
}
-
+
i = mapping->info.dir.first_dir_index =
first_cluster == 0 ? 0 : s->directory.next;
- /* actually read the directory, and allocate the mappings */
+ /* actually read the directory, and allocate the mappings */
while((entry=readdir(dir))) {
unsigned int length=strlen(dirname)+2+strlen(entry->d_name);
char* buffer;
@@ -690,7 +725,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
if(first_cluster == 0 && (is_dotdot || is_dot))
continue;
-
+
buffer=(char*)malloc(length);
assert(buffer);
snprintf(buffer,length,"%s/%s",dirname,entry->d_name);
@@ -765,7 +800,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
memset(array_get(&(s->directory), cur), 0,
(ROOT_ENTRIES - cur) * sizeof(direntry_t));
}
-
+
/* reget the mapping, since s->mapping was possibly realloc()ed */
mapping = (mapping_t*)array_get(&(s->mapping), mapping_index);
first_cluster += (s->directory.next - mapping->info.dir.first_dir_index)
@@ -774,7 +809,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
direntry = (direntry_t*)array_get(&(s->directory), mapping->dir_index);
set_begin_of_direntry(direntry, mapping->begin);
-
+
return 0;
}
@@ -825,7 +860,7 @@ static int init_directories(BDRVVVFATState* s,
*/
i = 1+s->sectors_per_cluster*0x200*8/s->fat_type;
s->sectors_per_fat=(s->sector_count+i)/i; /* round up */
-
+
array_init(&(s->mapping),sizeof(mapping_t));
array_init(&(s->directory),sizeof(direntry_t));
@@ -857,7 +892,7 @@ static int init_directories(BDRVVVFATState* s,
for (i = 0, cluster = 0; i < s->mapping.next; i++) {
int j;
- /* MS-DOS expects the FAT to be 0 for the root directory
+ /* MS-DOS expects the FAT to be 0 for the root directory
* (except for the media byte). */
/* LATER TODO: still true for FAT32? */
int fix_fat = (i != 0);
@@ -973,10 +1008,9 @@ DLOG(if (stderr == NULL) {
s->fat_type=16;
/* LATER TODO: if FAT32, adjust */
- s->sector_count=0xec04f;
s->sectors_per_cluster=0x10;
- /* LATER TODO: this could be wrong for FAT32 */
- bs->cyls=1023; bs->heads=15; bs->secs=63;
+ /* 504MB disk*/
+ bs->cyls=1024; bs->heads=16; bs->secs=63;
s->current_cluster=0xffffffff;
@@ -987,16 +1021,10 @@ DLOG(if (stderr == NULL) {
s->qcow_filename = NULL;
s->fat2 = NULL;
s->downcase_short_names = 1;
-
+
if (!strstart(dirname, "fat:", NULL))
return -1;
- if (strstr(dirname, ":rw:")) {
- if (enable_write_target(s))
- return -1;
- bs->read_only = 0;
- }
-
if (strstr(dirname, ":floppy:")) {
floppy = 1;
s->fat_type = 12;
@@ -1005,6 +1033,8 @@ DLOG(if (stderr == NULL) {
bs->cyls = 80; bs->heads = 2; bs->secs = 36;
}
+ s->sector_count=bs->cyls*bs->heads*bs->secs;
+
if (strstr(dirname, ":32:")) {
fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
s->fat_type = 32;
@@ -1015,6 +1045,12 @@ DLOG(if (stderr == NULL) {
s->sector_count=2880;
}
+ if (strstr(dirname, ":rw:")) {
+ if (enable_write_target(s))
+ return -1;
+ bs->read_only = 0;
+ }
+
i = strrchr(dirname, ':') - dirname;
assert(i >= 3);
if (dirname[i-2] == ':' && isalpha(dirname[i-1]))
@@ -1024,11 +1060,12 @@ DLOG(if (stderr == NULL) {
dirname += i+1;
bs->total_sectors=bs->cyls*bs->heads*bs->secs;
- if (s->sector_count > bs->total_sectors)
- s->sector_count = bs->total_sectors;
+
if(init_directories(s, dirname))
return -1;
+ s->sector_count = s->faked_sectors + s->sectors_per_cluster*s->cluster_count;
+
if(s->first_sectors_number==0x40)
init_mbr(s);
@@ -1076,7 +1113,7 @@ static inline int find_mapping_for_cluster_aux(BDRVVVFATState* s,int cluster_num
assert(index1<=index2);
DLOG(mapping=array_get(&(s->mapping),index1);
assert(mapping->begin<=cluster_num);
- assert(index2 >= s->mapping.next ||
+ assert(index2 >= s->mapping.next ||
((mapping = array_get(&(s->mapping),index2)) &&
mapping->end>cluster_num)));
}
@@ -1239,7 +1276,7 @@ static void print_mapping(const mapping_t* mapping)
}
#endif
-static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
+static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BDRVVVFATState *s = bs->opaque;
@@ -1674,7 +1711,7 @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
}
/*
- * This function looks at the modified data (qcow).
+ * This function looks at the modified data (qcow).
* It returns 0 upon inconsistency or error, and the number of clusters
* used by the directory, its subdirectories and their files.
*/
@@ -1709,7 +1746,7 @@ static int check_directory_consistency(BDRVVVFATState *s,
} else
/* new directory */
schedule_mkdir(s, cluster_num, strdup(path));
-
+
lfn_init(&lfn);
do {
int i;
@@ -2049,7 +2086,7 @@ static int commit_mappings(BDRVVVFATState* s,
}
next_mapping->dir_index = mapping->dir_index;
- next_mapping->first_mapping_index =
+ next_mapping->first_mapping_index =
mapping->first_mapping_index < 0 ?
array_index(&(s->mapping), mapping) :
mapping->first_mapping_index;
@@ -2069,7 +2106,7 @@ static int commit_mappings(BDRVVVFATState* s,
mapping = next_mapping;
}
-
+
cluster = c1;
}
@@ -2555,7 +2592,7 @@ static int do_commit(BDRVVVFATState* s)
return ret;
}
- /* copy FAT (with bdrv_read) */
+ /* copy FAT (with bdrv_read) */
memcpy(s->fat.pointer, s->fat2, 0x200 * s->sectors_per_fat);
/* recurse direntries from root (using bs->bdrv_read) */
@@ -2597,10 +2634,10 @@ DLOG(checkpoint());
return do_commit(s);
}
-static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
+static int vvfat_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
- BDRVVVFATState *s = bs->opaque;
+ BDRVVVFATState *s = bs->opaque;
int i, ret;
DLOG(checkpoint());
@@ -2639,7 +2676,7 @@ DLOG(checkpoint());
begin = sector_num;
if (end > sector_num + nb_sectors)
end = sector_num + nb_sectors;
- dir_index = mapping->dir_index +
+ dir_index = mapping->dir_index +
0x10 * (begin - mapping->begin * s->sectors_per_cluster);
direntries = (direntry_t*)(buf + 0x200 * (begin - sector_num));
@@ -2698,7 +2735,7 @@ static int vvfat_is_allocated(BlockDriverState *bs,
*n = nb_sectors;
else if (*n < 0)
return 0;
- return 1;
+ return 1;
}
static int write_target_commit(BlockDriverState *bs, int64_t sector_num,
diff --git a/block.c b/block.c
index 9264e42a6..3c7039947 100644
--- a/block.c
+++ b/block.c
@@ -1,8 +1,8 @@
/*
* QEMU System Emulator block 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
@@ -48,7 +48,7 @@ static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
int64_t sector_num, const uint8_t *buf, int nb_sectors,
BlockDriverCompletionFunc *cb, void *opaque);
static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
-static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
+static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
@@ -167,7 +167,7 @@ BlockDriver *bdrv_find_format(const char *format_name)
return NULL;
}
-int bdrv_create(BlockDriver *drv,
+int bdrv_create(BlockDriver *drv,
const char *filename, int64_t size_in_sectors,
const char *backing_file, int flags)
{
@@ -180,7 +180,7 @@ int bdrv_create(BlockDriver *drv,
void get_tmp_filename(char *filename, int size)
{
char temp_dir[MAX_PATH];
-
+
GetTempPath(MAX_PATH, temp_dir);
GetTempFileName(temp_dir, "qem", 0, filename);
}
@@ -202,10 +202,10 @@ static int is_windows_drive_prefix(const char *filename)
(filename[0] >= 'A' && filename[0] <= 'Z')) &&
filename[1] == ':');
}
-
+
static int is_windows_drive(const char *filename)
{
- if (is_windows_drive_prefix(filename) &&
+ if (is_windows_drive_prefix(filename) &&
filename[2] == '\0')
return 1;
if (strstart(filename, "\\\\.\\", NULL) ||
@@ -236,7 +236,7 @@ static BlockDriver *find_protocol(const char *filename)
memcpy(protocol, filename, len);
protocol[len] = '\0';
for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
- if (drv1->protocol_name &&
+ if (drv1->protocol_name &&
!strcmp(drv1->protocol_name, protocol))
return drv1;
}
@@ -251,7 +251,7 @@ static BlockDriver *find_image_format(const char *filename)
BlockDriver *drv1, *drv;
uint8_t buf[2048];
BlockDriverState *bs;
-
+
/* detect host devices. By convention, /dev/cdrom[N] is always
recognized as a host CDROM */
if (strstart(filename, "/dev/cdrom", NULL))
@@ -262,13 +262,13 @@ static BlockDriver *find_image_format(const char *filename)
#else
{
struct stat st;
- if (stat(filename, &st) >= 0 &&
+ if (stat(filename, &st) >= 0 &&
(S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
return &bdrv_host_device;
}
}
#endif
-
+
drv = find_protocol(filename);
/* no need to test disk image formats for vvfat */
if (drv == &bdrv_vvfat)
@@ -322,9 +322,9 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
BlockDriver *drv)
{
int ret, open_flags;
- char tmp_filename[1024];
- char backing_filename[1024];
-
+ char tmp_filename[PATH_MAX];
+ char backing_filename[PATH_MAX];
+
bs->read_only = 0;
bs->is_temporary = 0;
bs->encrypted = 0;
@@ -332,7 +332,7 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
if (flags & BDRV_O_SNAPSHOT) {
BlockDriverState *bs1;
int64_t total_size;
-
+
/* if snapshot, we create a temporary backing file and open it
instead of opening 'filename' directly */
@@ -347,10 +347,10 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
}
total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
bdrv_delete(bs1);
-
+
get_tmp_filename(tmp_filename, sizeof(tmp_filename));
realpath(filename, backing_filename);
- if (bdrv_create(&bdrv_qcow2, tmp_filename,
+ if (bdrv_create(&bdrv_qcow2, tmp_filename,
total_size, backing_filename, 0) < 0) {
return -1;
}
@@ -494,7 +494,7 @@ int bdrv_commit(BlockDriverState *bs)
}
/* return < 0 if error. See bdrv_write() for the return codes */
-int bdrv_read(BlockDriverState *bs, int64_t sector_num,
+int bdrv_read(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
BlockDriver *drv = bs->drv;
@@ -525,13 +525,13 @@ int bdrv_read(BlockDriverState *bs, int64_t sector_num,
}
}
-/* Return < 0 if error. Important errors are:
+/* Return < 0 if error. Important errors are:
-EIO generic I/O error (may happen for all errors)
-ENOMEDIUM No media inserted.
-EINVAL Invalid sector number or nb_sectors
-EACCES Trying to write a read-only device
*/
-int bdrv_write(BlockDriverState *bs, int64_t sector_num,
+int bdrv_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BlockDriver *drv = bs->drv;
@@ -540,7 +540,7 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
if (bs->read_only)
return -EACCES;
if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
- memcpy(bs->boot_sector_data, buf, 512);
+ memcpy(bs->boot_sector_data, buf, 512);
}
if (drv->bdrv_pwrite) {
int ret, len;
@@ -557,7 +557,7 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
}
}
-static int bdrv_pread_em(BlockDriverState *bs, int64_t offset,
+static int bdrv_pread_em(BlockDriverState *bs, int64_t offset,
uint8_t *buf, int count1)
{
uint8_t tmp_buf[SECTOR_SIZE];
@@ -601,7 +601,7 @@ static int bdrv_pread_em(BlockDriverState *bs, int64_t offset,
return count1;
}
-static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset,
+static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset,
const uint8_t *buf, int count1)
{
uint8_t tmp_buf[SECTOR_SIZE];
@@ -650,9 +650,9 @@ static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset,
}
/**
- * Read with byte offsets (needed only for file protocols)
+ * Read with byte offsets (needed only for file protocols)
*/
-int bdrv_pread(BlockDriverState *bs, int64_t offset,
+int bdrv_pread(BlockDriverState *bs, int64_t offset,
void *buf1, int count1)
{
BlockDriver *drv = bs->drv;
@@ -664,10 +664,10 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
return drv->bdrv_pread(bs, offset, buf1, count1);
}
-/**
- * Write with byte offsets (needed only for file protocols)
+/**
+ * Write with byte offsets (needed only for file protocols)
*/
-int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
+int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
const void *buf1, int count1)
{
BlockDriver *drv = bs->drv;
@@ -729,7 +729,7 @@ void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
memset(bs->boot_sector_data + size, 0, 512 - size);
}
-void bdrv_set_geometry_hint(BlockDriverState *bs,
+void bdrv_set_geometry_hint(BlockDriverState *bs,
int cyls, int heads, int secs)
{
bs->cyls = cyls;
@@ -749,7 +749,7 @@ void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
bs->translation = translation;
}
-void bdrv_get_geometry_hint(BlockDriverState *bs,
+void bdrv_get_geometry_hint(BlockDriverState *bs,
int *pcyls, int *pheads, int *psecs)
{
*pcyls = bs->cyls;
@@ -778,7 +778,7 @@ int bdrv_is_read_only(BlockDriverState *bs)
}
/* XXX: no longer used */
-void bdrv_set_change_cb(BlockDriverState *bs,
+void bdrv_set_change_cb(BlockDriverState *bs,
void (*change_cb)(void *opaque), void *opaque)
{
bs->change_cb = change_cb;
@@ -816,7 +816,7 @@ void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
}
}
-void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
+void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
void *opaque)
{
BlockDriver *drv;
@@ -899,7 +899,7 @@ void bdrv_info(void)
}
}
-void bdrv_get_backing_filename(BlockDriverState *bs,
+void bdrv_get_backing_filename(BlockDriverState *bs,
char *filename, int filename_size)
{
if (!bs->backing_hd) {
@@ -909,7 +909,7 @@ void bdrv_get_backing_filename(BlockDriverState *bs,
}
}
-int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
+int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
BlockDriver *drv = bs->drv;
@@ -919,7 +919,7 @@ int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num,
return -ENOTSUP;
return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
}
-
+
int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
{
BlockDriver *drv = bs->drv;
@@ -934,7 +934,7 @@ int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
/**************************************************************/
/* handling of snapshots */
-int bdrv_snapshot_create(BlockDriverState *bs,
+int bdrv_snapshot_create(BlockDriverState *bs,
QEMUSnapshotInfo *sn_info)
{
BlockDriver *drv = bs->drv;
@@ -945,7 +945,7 @@ int bdrv_snapshot_create(BlockDriverState *bs,
return drv->bdrv_snapshot_create(bs, sn_info);
}
-int bdrv_snapshot_goto(BlockDriverState *bs,
+int bdrv_snapshot_goto(BlockDriverState *bs,
const char *snapshot_id)
{
BlockDriver *drv = bs->drv;
@@ -966,7 +966,7 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
return drv->bdrv_snapshot_delete(bs, snapshot_id);
}
-int bdrv_snapshot_list(BlockDriverState *bs,
+int bdrv_snapshot_list(BlockDriverState *bs,
QEMUSnapshotInfo **psn_info)
{
BlockDriver *drv = bs->drv;
@@ -991,12 +991,12 @@ char *get_human_readable_size(char *buf, int buf_size, int64_t size)
base = 1024;
for(i = 0; i < NB_SUFFIXES; i++) {
if (size < (10 * base)) {
- snprintf(buf, buf_size, "%0.1f%c",
+ snprintf(buf, buf_size, "%0.1f%c",
(double)size / base,
suffixes[i]);
break;
} else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
- snprintf(buf, buf_size, "%" PRId64 "%c",
+ snprintf(buf, buf_size, "%" PRId64 "%c",
((size + (base >> 1)) / base),
suffixes[i]);
break;
@@ -1019,8 +1019,8 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
int64_t secs;
if (!sn) {
- snprintf(buf, buf_size,
- "%-10s%-20s%7s%20s%15s",
+ snprintf(buf, buf_size,
+ "%-10s%-20s%7s%20s%15s",
"ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
} else {
ti = sn->date_sec;
@@ -1038,10 +1038,10 @@ char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
"%02d:%02d:%02d.%03d",
(int)(secs / 3600),
(int)((secs / 60) % 60),
- (int)(secs % 60),
+ (int)(secs % 60),
(int)((sn->vm_clock_nsec / 1000000) % 1000));
snprintf(buf, buf_size,
- "%-10s%-20s%7s%20s%15s",
+ "%-10s%-20s%7s%20s%15s",
sn->id_str, sn->name,
get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
date_buf,
@@ -1062,7 +1062,7 @@ BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
if (!drv)
return NULL;
-
+
/* XXX: we assume that nb_sectors == 0 is suppored by the async read */
if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
memcpy(buf, bs->boot_sector_data, 512);
@@ -1085,7 +1085,7 @@ BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
if (bs->read_only)
return NULL;
if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
- memcpy(bs->boot_sector_data, buf, 512);
+ memcpy(bs->boot_sector_data, buf, 512);
}
return drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
@@ -1184,7 +1184,7 @@ static void bdrv_rw_em_cb(void *opaque, int ret)
#define NOT_DONE 0x7fffffff
-static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
+static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors)
{
int async_ret;
@@ -1192,7 +1192,7 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
async_ret = NOT_DONE;
qemu_aio_wait_start();
- acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors,
+ acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors,
bdrv_rw_em_cb, &async_ret);
if (acb == NULL) {
qemu_aio_wait_end();
@@ -1213,7 +1213,7 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
async_ret = NOT_DONE;
qemu_aio_wait_start();
- acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors,
+ acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors,
bdrv_rw_em_cb, &async_ret);
if (acb == NULL) {
qemu_aio_wait_end();
@@ -1241,6 +1241,7 @@ void bdrv_init(void)
bdrv_register(&bdrv_vpc);
bdrv_register(&bdrv_vvfat);
bdrv_register(&bdrv_qcow2);
+ bdrv_register(&bdrv_parallels);
}
void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
@@ -1292,7 +1293,7 @@ int bdrv_is_inserted(BlockDriverState *bs)
/**
* Return TRUE if the media changed since the last call to this
- * function. It is currently only used for floppy disks
+ * function. It is currently only used for floppy disks
*/
int bdrv_media_changed(BlockDriverState *bs)
{
diff --git a/block_int.h b/block_int.h
index 25f6717b5..b034023e0 100644
--- a/block_int.h
+++ b/block_int.h
@@ -1,8 +1,8 @@
/*
* QEMU System Emulator block 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
@@ -24,17 +24,21 @@
#ifndef BLOCK_INT_H
#define BLOCK_INT_H
+#define BLOCK_FLAG_ENCRYPT 1
+#define BLOCK_FLAG_COMPRESS 2
+#define BLOCK_FLAG_COMPAT6 4
+
struct BlockDriver {
const char *format_name;
int instance_size;
int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags);
- int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
+ int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
- int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
+ int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
void (*bdrv_close)(BlockDriverState *bs);
- int (*bdrv_create)(const char *filename, int64_t total_sectors,
+ int (*bdrv_create)(const char *filename, int64_t total_sectors,
const char *backing_file, int flags);
void (*bdrv_flush)(BlockDriverState *bs);
int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
@@ -52,21 +56,21 @@ struct BlockDriver {
int aiocb_size;
const char *protocol_name;
- int (*bdrv_pread)(BlockDriverState *bs, int64_t offset,
+ int (*bdrv_pread)(BlockDriverState *bs, int64_t offset,
uint8_t *buf, int count);
- int (*bdrv_pwrite)(BlockDriverState *bs, int64_t offset,
+ int (*bdrv_pwrite)(BlockDriverState *bs, int64_t offset,
const uint8_t *buf, int count);
int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
int64_t (*bdrv_getlength)(BlockDriverState *bs);
- int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
+ int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
- int (*bdrv_snapshot_create)(BlockDriverState *bs,
+ int (*bdrv_snapshot_create)(BlockDriverState *bs,
QEMUSnapshotInfo *sn_info);
- int (*bdrv_snapshot_goto)(BlockDriverState *bs,
+ int (*bdrv_snapshot_goto)(BlockDriverState *bs,
const char *snapshot_id);
int (*bdrv_snapshot_delete)(BlockDriverState *bs, const char *snapshot_id);
- int (*bdrv_snapshot_list)(BlockDriverState *bs,
+ int (*bdrv_snapshot_list)(BlockDriverState *bs,
QEMUSnapshotInfo **psn_info);
int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
@@ -75,7 +79,7 @@ struct BlockDriver {
int (*bdrv_media_changed)(BlockDriverState *bs);
int (*bdrv_eject)(BlockDriverState *bs, int eject_flag);
int (*bdrv_set_locked)(BlockDriverState *bs, int locked);
-
+
BlockDriverAIOCB *free_aiocb;
struct BlockDriver *next;
};
@@ -107,7 +111,7 @@ struct BlockDriverState {
/* async read/write emulation */
void *sync_aiocb;
-
+
/* NOTE: the following infos are only hints for real hardware
drivers. They are not used by the block driver */
int cyls, heads, secs, translation;
diff --git a/bswap.h b/bswap.h
index 37fb04ed9..970c1bbe3 100644
--- a/bswap.h
+++ b/bswap.h
@@ -48,12 +48,12 @@ static inline uint16_t bswap16(uint16_t x)
return bswap_16(x);
}
-static inline uint32_t bswap32(uint32_t x)
+static inline uint32_t bswap32(uint32_t x)
{
return bswap_32(x);
}
-static inline uint64_t bswap64(uint64_t x)
+static inline uint64_t bswap64(uint64_t x)
{
return bswap_64(x);
}
diff --git a/cocoa.m b/cocoa.m
index 9551affa3..84f943c5b 100644
--- a/cocoa.m
+++ b/cocoa.m
@@ -1,9 +1,9 @@
/*
* QEMU Cocoa display driver
- *
+ *
* Copyright (c) 2005 Pierre d'Herbemont
* many code/inspiration from SDL 1.2 code (LGPL)
- *
+ *
* 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
@@ -23,7 +23,7 @@
* THE SOFTWARE.
*/
/*
- Todo : x miniaturize window
+ Todo : x miniaturize window
x center the window
- save window position
- handle keyboard event
@@ -84,7 +84,7 @@ static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
MacSetRectRgn (temp, x, y,
x + w, y + h);
MacUnionRgn (dirty, temp, dirty);
-
+
/* Flush the dirty region */
QDFlushPortBuffer ( [ qd_view qdPort ], dirty );
DisposeRgn (dirty);
@@ -102,9 +102,9 @@ static void cocoa_resize(DisplayState *ds, int w, int h)
static void *screen_pixels;
static int screen_pitch;
NSRect contentRect;
-
+
//printf("resizing to %d %d\n", w, h);
-
+
contentRect = NSMakeRect (0, 0, w, h);
if(window)
{
@@ -119,44 +119,44 @@ static void cocoa_resize(DisplayState *ds, int w, int h)
fprintf(stderr, "(cocoa) can't create window\n");
exit(1);
}
-
+
if(qd_view)
[qd_view release];
-
+
qd_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ];
-
+
if(!qd_view)
{
fprintf(stderr, "(cocoa) can't create qd_view\n");
exit(1);
}
-
+
[ window setAcceptsMouseMovedEvents:YES ];
[ window setTitle:@"Qemu" ];
[ window setReleasedWhenClosed:NO ];
-
+
/* Set screen to black */
[ window setBackgroundColor: [NSColor blackColor] ];
-
+
/* set window position */
[ window center ];
-
+
[ qd_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
[ [ window contentView ] addSubview:qd_view ];
[ qd_view release ];
[ window makeKeyAndOrderFront:nil ];
-
+
/* Careful here, the window seems to have to be onscreen to do that */
LockPortBits ( [ qd_view qdPort ] );
screen_pixels = GetPixBaseAddr ( GetPortPixMap ( [ qd_view qdPort ] ) );
screen_pitch = GetPixRowBytes ( GetPortPixMap ( [ qd_view qdPort ] ) );
UnlockPortBits ( [ qd_view qdPort ] );
- {
- int vOffset = [ window frame ].size.height -
+ {
+ int vOffset = [ window frame ].size.height -
[ qd_view frame ].size.height - [ qd_view frame ].origin.y;
-
+
int hOffset = [ qd_view frame ].origin.x;
-
+
screen_pixels += (vOffset * screen_pitch) + hOffset * (device_bpp/8);
}
ds->data = screen_pixels;
@@ -164,7 +164,12 @@ static void cocoa_resize(DisplayState *ds, int w, int h)
ds->depth = device_bpp;
ds->width = w;
ds->height = h;
-
+#ifdef __LITTLE_ENDIAN__
+ ds->bgr = 1;
+#else
+ ds->bgr = 0;
+#endif
+
current_ds = *ds;
}
@@ -305,38 +310,38 @@ int keymap[] =
208,// 125 0x7D 0xd0 E0,50 D ARROW QZ_DOWN
200,// 126 0x7E 0xc8 E0,48 U ARROW QZ_UP
/* completed according to http://www.libsdl.org/cgi/cvsweb.cgi/SDL12/src/video/quartz/SDL_QuartzKeys.h?rev=1.6&content-type=text/x-cvsweb-markup */
-
+
/* Aditional 104 Key XP-Keyboard Scancodes from http://www.computer-engineering.org/ps2keyboard/scancodes1.html */
/*
- 219 // 0xdb e0,5b L GUI
- 220 // 0xdc e0,5c R GUI
- 221 // 0xdd e0,5d APPS
- // E0,2A,E0,37 PRNT SCRN
- // E1,1D,45,E1,9D,C5 PAUSE
- 83 // 0x53 0x53 KP .
-// ACPI Scan Codes
- 222 // 0xde E0, 5E Power
- 223 // 0xdf E0, 5F Sleep
- 227 // 0xe3 E0, 63 Wake
-// Windows Multimedia Scan Codes
- 153 // 0x99 E0, 19 Next Track
- 144 // 0x90 E0, 10 Previous Track
- 164 // 0xa4 E0, 24 Stop
- 162 // 0xa2 E0, 22 Play/Pause
- 160 // 0xa0 E0, 20 Mute
- 176 // 0xb0 E0, 30 Volume Up
- 174 // 0xae E0, 2E Volume Down
- 237 // 0xed E0, 6D Media Select
- 236 // 0xec E0, 6C E-Mail
- 161 // 0xa1 E0, 21 Calculator
- 235 // 0xeb E0, 6B My Computer
- 229 // 0xe5 E0, 65 WWW Search
- 178 // 0xb2 E0, 32 WWW Home
- 234 // 0xea E0, 6A WWW Back
- 233 // 0xe9 E0, 69 WWW Forward
- 232 // 0xe8 E0, 68 WWW Stop
- 231 // 0xe7 E0, 67 WWW Refresh
- 230 // 0xe6 E0, 66 WWW Favorites
+ 219 // 0xdb e0,5b L GUI
+ 220 // 0xdc e0,5c R GUI
+ 221 // 0xdd e0,5d APPS
+ // E0,2A,E0,37 PRNT SCRN
+ // E1,1D,45,E1,9D,C5 PAUSE
+ 83 // 0x53 0x53 KP .
+// ACPI Scan Codes
+ 222 // 0xde E0, 5E Power
+ 223 // 0xdf E0, 5F Sleep
+ 227 // 0xe3 E0, 63 Wake
+// Windows Multimedia Scan Codes
+ 153 // 0x99 E0, 19 Next Track
+ 144 // 0x90 E0, 10 Previous Track
+ 164 // 0xa4 E0, 24 Stop
+ 162 // 0xa2 E0, 22 Play/Pause
+ 160 // 0xa0 E0, 20 Mute
+ 176 // 0xb0 E0, 30 Volume Up
+ 174 // 0xae E0, 2E Volume Down
+ 237 // 0xed E0, 6D Media Select
+ 236 // 0xec E0, 6C E-Mail
+ 161 // 0xa1 E0, 21 Calculator
+ 235 // 0xeb E0, 6B My Computer
+ 229 // 0xe5 E0, 65 WWW Search
+ 178 // 0xb2 E0, 32 WWW Home
+ 234 // 0xea E0, 6A WWW Back
+ 233 // 0xe9 E0, 69 WWW Forward
+ 232 // 0xe8 E0, 68 WWW Stop
+ 231 // 0xe7 E0, 67 WWW Refresh
+ 230 // 0xe6 E0, 66 WWW Favorites
*/
};
@@ -361,10 +366,10 @@ static void cocoa_refresh(DisplayState *ds)
NSDate *distantPast;
NSEvent *event;
NSAutoreleasePool *pool;
-
+
pool = [ [ NSAutoreleasePool alloc ] init ];
distantPast = [ NSDate distantPast ];
-
+
vga_hw_update();
do {
@@ -410,8 +415,8 @@ static void cocoa_refresh(DisplayState *ds)
case NSKeyDown:
{
- int keycode = cocoa_keycode_to_qemu([event keyCode]);
-
+ int keycode = cocoa_keycode_to_qemu([event keyCode]);
+
/* handle command Key Combos */
if ([event modifierFlags] & NSCommandKeyMask) {
switch ([event keyCode]) {
@@ -422,7 +427,7 @@ static void cocoa_refresh(DisplayState *ds)
return;
}
}
-
+
/* handle control + alt Key Combos */
if (([event modifierFlags] & NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) {
switch (keycode) {
@@ -477,10 +482,10 @@ static void cocoa_refresh(DisplayState *ds)
}
}
break;
-
+
case NSKeyUp:
{
- int keycode = cocoa_keycode_to_qemu([event keyCode]);
+ int keycode = cocoa_keycode_to_qemu([event keyCode]);
if (is_graphic_console()) {
if (keycode & 0x80)
kbd_put_keycode(0xe0);
@@ -488,7 +493,7 @@ static void cocoa_refresh(DisplayState *ds)
}
}
break;
-
+
case NSMouseMoved:
if (grab) {
int dx = [event deltaX];
@@ -498,11 +503,11 @@ static void cocoa_refresh(DisplayState *ds)
kbd_mouse_event(dx, dy, dz, buttons);
}
break;
-
+
case NSLeftMouseDown:
if (grab) {
int buttons = 0;
-
+
/* leftclick+command simulates rightclick */
if ([event modifierFlags] & NSCommandKeyMask) {
buttons |= MOUSE_EVENT_RBUTTON;
@@ -514,7 +519,7 @@ static void cocoa_refresh(DisplayState *ds)
[NSApp sendEvent: event];
}
break;
-
+
case NSLeftMouseDragged:
if (grab) {
int dx = [event deltaX];
@@ -529,7 +534,7 @@ static void cocoa_refresh(DisplayState *ds)
kbd_mouse_event(dx, dy, dz, buttons);
}
break;
-
+
case NSLeftMouseUp:
if (grab) {
kbd_mouse_event(0, 0, 0, 0);
@@ -541,18 +546,18 @@ static void cocoa_refresh(DisplayState *ds)
//[NSApp sendEvent: event];
}
break;
-
+
case NSRightMouseDown:
if (grab) {
int buttons = 0;
-
+
buttons |= MOUSE_EVENT_RBUTTON;
kbd_mouse_event(0, 0, 0, buttons);
} else {
[NSApp sendEvent: event];
}
break;
-
+
case NSRightMouseDragged:
if (grab) {
int dx = [event deltaX];
@@ -563,7 +568,7 @@ static void cocoa_refresh(DisplayState *ds)
kbd_mouse_event(dx, dy, dz, buttons);
}
break;
-
+
case NSRightMouseUp:
if (grab) {
kbd_mouse_event(0, 0, 0, 0);
@@ -571,7 +576,7 @@ static void cocoa_refresh(DisplayState *ds)
[NSApp sendEvent: event];
}
break;
-
+
case NSOtherMouseDragged:
if (grab) {
int dx = [event deltaX];
@@ -582,7 +587,7 @@ static void cocoa_refresh(DisplayState *ds)
kbd_mouse_event(dx, dy, dz, buttons);
}
break;
-
+
case NSOtherMouseDown:
if (grab) {
int buttons = 0;
@@ -592,7 +597,7 @@ static void cocoa_refresh(DisplayState *ds)
[NSApp sendEvent:event];
}
break;
-
+
case NSOtherMouseUp:
if (grab) {
kbd_mouse_event(0, 0, 0, 0);
@@ -600,14 +605,14 @@ static void cocoa_refresh(DisplayState *ds)
[NSApp sendEvent: event];
}
break;
-
+
case NSScrollWheel:
if (grab) {
int dz = [event deltaY];
kbd_mouse_event(0, 0, -dz, 0);
}
break;
-
+
default: [NSApp sendEvent:event];
}
}
@@ -620,7 +625,7 @@ static void cocoa_refresh(DisplayState *ds)
------------------------------------------------------
*/
-static void cocoa_cleanup(void)
+static void cocoa_cleanup(void)
{
}
@@ -636,9 +641,9 @@ void cocoa_display_init(DisplayState *ds, int full_screen)
ds->dpy_update = cocoa_update;
ds->dpy_resize = cocoa_resize;
ds->dpy_refresh = cocoa_refresh;
-
+
cocoa_resize(ds, 640, 400);
-
+
atexit(cocoa_cleanup);
}
@@ -656,17 +661,17 @@ void cocoa_display_init(DisplayState *ds, int full_screen)
------------------------------------------------------
*/
static void QZ_SetPortAlphaOpaque ()
-{
+{
/* Assume 32 bit if( bpp == 32 )*/
if ( 1 ) {
-
+
uint32_t *pixels = (uint32_t*) current_ds.data;
uint32_t rowPixels = current_ds.linesize / 4;
uint32_t i, j;
-
+
for (i = 0; i < current_ds.height; i++)
for (j = 0; j < current_ds.width; j++) {
-
+
pixels[ (i * rowPixels) + j ] |= 0xFF000000;
}
}
@@ -675,32 +680,32 @@ static void QZ_SetPortAlphaOpaque ()
@implementation QemuWindow
- (void)miniaturize:(id)sender
{
-
+
/* make the alpha channel opaque so anim won't have holes in it */
QZ_SetPortAlphaOpaque ();
-
+
[ super miniaturize:sender ];
-
+
}
- (void)display
-{
- /*
+{
+ /*
This method fires just before the window deminaturizes from the Dock.
-
+
We'll save the current visible surface, let the window manager redraw any
- UI elements, and restore the SDL surface. This way, no expose event
+ UI elements, and restore the SDL surface. This way, no expose event
is required, and the deminiaturize works perfectly.
*/
-
+
/* make sure pixels are fully opaque */
QZ_SetPortAlphaOpaque ();
-
+
/* save current visible SDL surface */
[ self cacheImageInRect:[ qd_view frame ] ];
-
+
/* let the window manager redraw controls, border, etc */
[ super display ];
-
+
/* restore visible SDL surface */
[ self restoreCachedImage ];
}
@@ -737,13 +742,13 @@ static void QZ_SetPortAlphaOpaque ()
if( gArgc <= 1 || strncmp (gArgv[1], "-psn", 4) == 0)
{
NSOpenPanel *op = [[NSOpenPanel alloc] init];
-
+
cocoa_resize(&current_ds, 640, 400);
-
+
[op setPrompt:@"Boot image"];
-
+
[op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"];
-
+
[op beginSheetForDirectory:nil file:nil types:[NSArray arrayWithObjects:@"img",@"iso",@"dmg",@"qcow",@"cow",@"cloop",@"vmdk",nil]
modalForWindow:window modalDelegate:self
didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:NULL];
@@ -769,20 +774,20 @@ static void QZ_SetPortAlphaOpaque ()
{
exit(0);
}
-
+
if(returnCode == NSOKButton)
{
char *bin = "qemu";
char *img = (char*)[ [ sheet filename ] cString];
-
+
char **argv = (char**)malloc( sizeof(char*)*3 );
-
+
asprintf(&argv[0], "%s", bin);
asprintf(&argv[1], "-hda");
asprintf(&argv[2], "%s", img);
-
+
printf("Using argc %d argv %s -hda %s\n", 3, bin, img);
-
+
[self startEmulationWithArgc:3 argv:(char**)argv];
}
}
@@ -822,10 +827,10 @@ static void setApplicationMenu(void)
NSMenuItem *menuItem;
NSString *title;
NSString *appName;
-
+
appName = @"Qemu";
appleMenu = [[NSMenu alloc] initWithTitle:@""];
-
+
/* Add menu items */
title = [@"About " stringByAppendingString:appName];
[appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""];
@@ -845,7 +850,7 @@ static void setApplicationMenu(void)
title = [@"Quit " stringByAppendingString:appName];
[appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"];
-
+
/* Put menu into the menubar */
menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
[menuItem setSubmenu:appleMenu];
@@ -867,17 +872,17 @@ static void setupWindowMenu(void)
NSMenuItem *menuItem;
windowMenu = [[NSMenu alloc] initWithTitle:@"Window"];
-
+
/* "Minimize" item */
menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"];
[windowMenu addItem:menuItem];
[menuItem release];
-
+
/* Put menu into the menubar */
windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""];
[windowMenuItem setSubmenu:windowMenu];
[[NSApp mainMenu] addItem:windowMenuItem];
-
+
/* Tell the application object that this is now the window menu */
[NSApp setWindowsMenu:windowMenu];
@@ -891,14 +896,14 @@ static void CustomApplicationMain(void)
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
QemuCocoaGUIController *gui_controller;
CPSProcessSerNum PSN;
-
+
[NSApplication sharedApplication];
-
+
if (!CPSGetCurrentProcess(&PSN))
if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
if (!CPSSetFrontProcess(&PSN))
[NSApplication sharedApplication];
-
+
/* Set up the menubar */
[NSApp setMainMenu:[[NSMenu alloc] init]];
setApplicationMenu();
@@ -907,10 +912,10 @@ static void CustomApplicationMain(void)
/* Create SDLMain and make it the app delegate */
gui_controller = [[QemuCocoaGUIController alloc] init];
[NSApp setDelegate:gui_controller];
-
+
/* Start the main event loop */
[NSApp run];
-
+
[gui_controller release];
[pool release];
}
diff --git a/configure b/configure
index bcff13e97..ebc294ebe 100755
--- a/configure
+++ b/configure
@@ -23,7 +23,7 @@ static="no"
cross_prefix=""
cc="gcc"
gcc3_search="yes"
-gcc3_list="gcc-3.4 gcc34 gcc-3.3 gcc33 gcc-3.2 gcc32"
+gcc3_list="gcc-3.4 gcc34 gcc-3.3.6 gcc-3.3 gcc33 gcc-3.2 gcc32"
host_cc="gcc"
ar="ar"
make="make"
@@ -50,10 +50,13 @@ case "$cpu" in
mips)
cpu="mips"
;;
- s390)
+ mips64)
+ cpu="mips64"
+ ;;
+ s390*)
cpu="s390"
;;
- sparc|sun4[muv])
+ sparc|sun4[cdmuv])
cpu="sparc"
;;
sparc64)
@@ -86,6 +89,7 @@ alsa="no"
fmod="no"
fmod_lib=""
fmod_inc=""
+vnc_tls="yes"
bsd="no"
linux="no"
kqemu="no"
@@ -105,9 +109,22 @@ case $targetos in
CYGWIN*)
mingw32="yes"
OS_CFLAGS="-mno-cygwin"
+VL_OS_LDFLAGS="-mno-cygwin"
+if [ "$cpu" = "i386" ] ; then
+ kqemu="yes"
+fi
;;
MINGW32*)
mingw32="yes"
+if [ "$cpu" = "i386" ] ; then
+ kqemu="yes"
+fi
+;;
+GNU/kFreeBSD)
+oss="yes"
+if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
+ kqemu="yes"
+fi
;;
FreeBSD)
bsd="yes"
@@ -133,7 +150,36 @@ coreaudio="yes"
OS_CFLAGS="-mdynamic-no-pic"
;;
SunOS)
-solaris="yes"
+ solaris="yes"
+ make="gmake"
+ install="ginstall"
+ needs_libsunmath="no"
+ solarisrev=`uname -r | cut -f2 -d.`
+ # have to select again, because `uname -m` returns i86pc
+ # even on an x86_64 box.
+ solariscpu=`isainfo -k`
+ if test "${solariscpu}" = "amd64" ; then
+ cpu="x86_64"
+ fi
+ if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
+ if test "$solarisrev" -le 9 ; then
+ if test -f /opt/SUNWspro/prod/lib/libsunmath.so.1; then
+ needs_libsunmath="yes"
+ else
+ echo "QEMU will not link correctly on Solaris 8/X86 or 9/x86 without"
+ echo "libsunmath from the Sun Studio compilers tools, due to a lack of"
+ echo "C99 math features in libm.so in Solaris 8/x86 and Solaris 9/x86"
+ echo "Studio 11 can be downloaded from www.sun.com."
+ exit 1
+ fi
+ fi
+ if test "$solarisrev" -ge 9 ; then
+ kqemu="yes"
+ fi
+ fi
+ if test -f /usr/include/sys/soundcard.h ; then
+ oss=yes
+ fi
;;
*)
oss="yes"
@@ -151,17 +197,6 @@ if [ "$bsd" = "yes" ] ; then
fi
fi
-if [ "$solaris" = "yes" ] ; then
- make="gmake"
- install="ginstall"
- solarisrev=`uname -r | cut -f2 -d.`
- if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
- if test "$solarisrev" -gt 10 ; then
- kqemu="yes"
- fi
- fi
-fi
-
# find source path
source_path=`dirname "$0"`
if [ -z "$source_path" ]; then
@@ -224,7 +259,9 @@ for opt do
;;
--fmod-inc=*) fmod_inc="$optarg"
;;
- --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; user="no"
+ --disable-vnc-tls) vnc_tls="no"
+ ;;
+ --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" ; linux_user="no"
;;
--disable-slirp) slirp="no"
;;
@@ -254,13 +291,64 @@ for opt do
;;
--enable-uname-release=*) uname_release="$optarg"
;;
+ --sparc_cpu=*)
+ sparc_cpu="$optarg"
+ case $sparc_cpu in
+ v7|v8) SP_CFLAGS="-m32 -mcpu=${sparc_cpu} -D__sparc_${sparc_cpu}__"; SP_LDFLAGS="-m32"
+ target_cpu="sparc"; cpu="sparc" ;;
+ v8plus|v8plusa) SP_CFLAGS="-m32 -mcpu=ultrasparc -D__sparc_${sparc_cpu}__"; SP_LDFLAGS="-m32"
+ target_cpu="sparc"; cpu="sparc" ;;
+ v9) SP_CFLAGS="-m64 -mcpu=ultrasparc -D__sparc_${sparc_cpu}__"; SP_LDFLAGS="-m64"
+ target_cpu="sparc64"; cpu="sparc64" ;;
+ *) echo "undefined SPARC architecture. Exiting";exit 1;;
+ esac
+ ;;
esac
done
+if [ "$bsd" = "yes" -o "$darwin" = "yes" -o "$mingw32" = "yes" ] ; then
+ AIOLIBS=
+else
+ AIOLIBS="-lrt"
+fi
+
# default flags for all hosts
CFLAGS="$CFLAGS -Wall -O2 -g -fno-strict-aliasing"
LDFLAGS="$LDFLAGS -g"
+#
+# If cpu ~= sparc and sparc_cpu hasn't been defined, plug in the right
+# ARCH_CFLAGS/ARCH_LDFLAGS (assume sparc_v8plus for 32-bit and sparc_v9 for 64-bit)
+#
+case $cpu in
+ sparc) if test -z "$sparc_cpu" ; then
+ ARCH_CFLAGS="-m32 -mcpu=ultrasparc -D__sparc_v8plus__"
+ ARCH_LDFLAGS="-m32"
+ else
+ ARCH_CFLAGS="${SP_CFLAGS}"
+ ARCH_LDFLAGS="${SP_LDFLAGS}"
+ fi
+ ;;
+ sparc64) if test -z "$sparc_cpu" ; then
+ ARCH_CFLAGS="-m64 -mcpu=ultrasparc -D__sparc_v9__"
+ ARCH_LDFLAGS="-m64"
+ else
+ ARCH_CFLAGS="${SP_CFLAGS}"
+ ARCH_LDFLAGS="${SP_LDFLAGS}"
+ fi
+ ;;
+esac
+
+if [ "$solaris" = "yes" -a "$cpu" = "x86_64" ] ; then
+ CFLAGS="${CFLAGS} -m64"
+ OS_CFLAGS="${OS_CFLAGS} -m64"
+fi
+
+if [ "$solaris" = "yes" -a "$cpu" = "i386" ] ; then
+ CFLAGS="${CFLAGS} -m32"
+ OS_CFLAGS="${OS_CFLAGS} -m32"
+fi
+
if test x"$show_help" = x"yes" ; then
cat << EOF
@@ -292,7 +380,8 @@ echo " --enable-adlib enable Adlib emulation"
echo " --enable-coreaudio enable Coreaudio audio driver"
echo " --enable-alsa enable ALSA audio driver"
echo " --enable-fmod enable FMOD audio driver"
-echo " --enabled-dsound enable DirectSound audio driver"
+echo " --enable-dsound enable DirectSound audio driver"
+echo " --disable-vnc-tls disable TLS encryption for VNC server"
echo " --enable-system enable all system emulation targets"
echo " --disable-system disable all system emulation targets"
echo " --enable-linux-user enable all linux usermode emulation targets"
@@ -302,6 +391,7 @@ echo " --disable-darwin-user disable all darwin usermode emulation targets"
echo " --fmod-lib path to FMOD library"
echo " --fmod-inc path to FMOD includes"
echo " --enable-uname-release=R Return R for uname -r in usermode emulation"
+echo " --sparc_cpu=V Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9"
echo ""
echo "NOTE: The object files are built at the place where configure is launched"
exit 1
@@ -316,7 +406,7 @@ cat > $TMPC <<EOF
int main(void) {}
EOF
-if $cc -c -o $TMPO $TMPC 2>/dev/null ; then
+if $cc -c -o $TMPO $TMPC 2> /dev/null ; then
: C compiler works ok
else
echo "ERROR: \"$cc\" either does not exist or does not work"
@@ -327,12 +417,9 @@ if test "$mingw32" = "yes" ; then
linux="no"
EXESUF=".exe"
oss="no"
- if [ "$cpu" = "i386" ] ; then
- kqemu="yes"
- fi
fi
-# Check for gcc4, error if pre-gcc4
+# Check for gcc4, error if pre-gcc4
if test "$check_gcc" = "yes" ; then
cat > $TMPC <<EOF
#if __GNUC__ < 4
@@ -340,20 +427,15 @@ if test "$check_gcc" = "yes" ; then
#endif
int main(){return 0;}
EOF
- check_cc() {
- which "$1" >&/dev/null
- return $?
- }
-
- if "$cc" -o $TMPE $TMPC 2>/dev/null ; then
+ if "$cc" -o $TMPE $TMPC 2> /dev/null ; then
echo "WARNING: \"$cc\" looks like gcc 4.x"
found_compat_cc="no"
if test "$gcc3_search" = "yes" ; then
echo "Looking for gcc 3.x"
for compat_cc in $gcc3_list ; do
- if check_cc "$compat_cc" ; then
+ if "$cross_prefix$compat_cc" --version 2> /dev/null | fgrep '(GCC) 3.' > /dev/null 2>&1 ; then
echo "Found \"$compat_cc\""
- cc="$compat_cc"
+ cc="$cross_prefix$compat_cc"
found_compat_cc="yes"
break
fi
@@ -378,7 +460,7 @@ if test "$solaris" = "yes" ; then
#
# gcc for solaris 10/fcs in /usr/sfw/bin doesn't compile qemu correctly
# override the check with --disable-gcc-check
- #
+ #
if test "$solarisrev" -eq 10 -a "$check_gcc" = "yes" ; then
solgcc=`which $cc`
if test "$solgcc" = "/usr/sfw/bin/gcc" ; then
@@ -409,17 +491,17 @@ if test "$solaris" = "yes" ; then
fi
exit 1
fi
-fi
+fi
if test -z "$target_list" ; then
# these targets are portable
if [ "$softmmu" = "yes" ] ; then
- target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu arm-softmmu"
+ target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu mips64-softmmu mips64el-softmmu arm-softmmu ppc64-softmmu ppcemb-softmmu m68k-softmmu sh4-softmmu"
fi
# the following are Linux specific
if [ "$linux_user" = "yes" ] ; then
- target_list="i386-linux-user arm-linux-user armeb-linux-user sparc-linux-user ppc-linux-user mips-linux-user mipsel-linux-user m68k-linux-user $target_list"
+ target_list="i386-linux-user arm-linux-user armeb-linux-user sparc-linux-user ppc-linux-user mips-linux-user mipsel-linux-user m68k-linux-user alpha-linux-user ppc64-linux-user sh4-linux-user $target_list"
fi
# the following are Darwin specific
if [ "$darwin_user" = "yes" ] ; then
@@ -445,7 +527,7 @@ int main(int argc, char ** argv){
}
EOF
-if $cc -o $TMPE $TMPC 2>/dev/null ; then
+if $cc -o $TMPE $TMPC 2> /dev/null ; then
$TMPE && bigendian="yes"
else
echo big/little test failed
@@ -454,7 +536,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" -o "$cpu" = "m68k" -o "$cpu" = "armv4b"; then
+if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "mips64" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k" -o "$cpu" = "armv4b"; then
bigendian="yes"
fi
@@ -472,71 +554,70 @@ int main(void) {
}
EOF
-have_gcc3_options="no"
-if $cc -fno-reorder-blocks -fno-optimize-sibling-calls -o $TMPO $TMPC 2> /dev/null ; then
- have_gcc3_options="yes"
-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
+ 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
+ if $cc -o $TMPE `$sdl_config --cflags 2> /dev/null` $TMPC `$sdl_config --libs 2> /dev/null` 2> /tmp/qemu-$$-sdl-config.log ; then
+ _sdlversion=`$sdl_config --version | sed 's/[^0-9]//g'`
+ if test "$_sdlversion" -lt 121 ; then
+ sdl_too_old=yes
+ else
+ if test "$cocoa" = "no" ; then
+ sdl=yes
+ fi
+ fi
+
+ # static link with sdl ?
+ if test "$sdl" = "yes" ; then
+ aa="no"
+ `$sdl_config --static-libs 2>/dev/null | grep \\\-laa > /dev/null` && aa="yes"
+ sdl_static_libs=`$sdl_config --static-libs 2>/dev/null`
+ 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
else
- if test "$cocoa" = "no" ; then
- sdl=yes
- fi
-fi
+ # Make sure to disable cocoa if sdl was set
+ if test "$sdl" = "yes" ; then
+ cocoa="no"
+ coreaudio="no"
+ fi
+fi # -z $sdl
-# 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`"
+##########################################
+# VNC TLS detection
+if test "$vnc_tls" = "yes" ; then
+ `pkg-config gnutls` || vnc_tls="no"
fi
-
-if $cc -o $TMPE `$sdl_config --cflags 2> /dev/null` $TMPC $sdl_static_libs 2> /dev/null; then
- sdl_static=yes
+if test "$vnc_tls" = "yes" ; then
+ vnc_tls_cflags=`pkg-config --cflags gnutls`
+ vnc_tls_libs=`pkg-config --libs gnutls`
fi
-fi # static link
-
-fi # sdl compile test
-
-fi # cross compilation
-
-else
- # Make sure to disable cocoa if sdl was set
- if test "$sdl" = "yes" ; then
- cocoa="no"
- coreaudio="no"
- fi
-fi # -z $sdl
-
##########################################
# alsa sound support libraries
@@ -557,33 +638,34 @@ EOF
fi
# Check if tools are available to build documentation.
-if [ -x "`which texi2html`" ] && [ -x "`which pod2man`" ]; then
+if [ -x "`which texi2html 2>/dev/null`" ] && \
+ [ -x "`which pod2man 2>/dev/null`" ]; then
build_docs="yes"
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"
+ if test -z "$prefix" ; then
+ prefix="/c/Program Files/Qemu"
+ fi
+ mansuffix=""
+ datasuffix=""
+ docsuffix=""
+ binsuffix=""
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"
+ if test -z "$prefix" ; then
+ prefix="/usr/local"
+ fi
+ mansuffix="/share/man"
+ datasuffix="/share/qemu"
+ docsuffix="/share/doc/qemu"
+ binsuffix="/bin"
fi
echo "Install prefix $prefix"
-echo "BIOS directory $datadir"
-echo "binary directory $bindir"
+echo "BIOS directory $prefix$datasuffix"
+echo "binary directory $prefix$binsuffix"
if test "$mingw32" = "no" ; then
-echo "Manual directory $mandir"
+echo "Manual directory $prefix$mansuffix"
echo "ELF interp prefix $interp_prefix"
fi
echo "Source path $source_path"
@@ -622,6 +704,15 @@ else
fmod_support=""
fi
echo "FMOD support $fmod $fmod_support"
+echo "OSS support $oss"
+echo "VNC TLS support $vnc_tls"
+if test "$vnc_tls" = "yes" ; then
+ echo " TLS CFLAGS $vnc_tls_cflags"
+ echo " TLS LIBS $vnc_tls_libs"
+fi
+if test -n "$sparc_cpu"; then
+ echo "Target Sparc Arch $sparc_cpu"
+fi
echo "kqemu support $kqemu"
echo "Documentation $build_docs"
[ ! -z "$uname_release" ] && \
@@ -630,6 +721,11 @@ echo "uname -r $uname_release"
if test $sdl_too_old = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
fi
+if [ -s /tmp/qemu-$$-sdl-config.log ]; then
+ echo "The error log from compiling the libSDL test is: "
+ cat /tmp/qemu-$$-sdl-config.log
+fi
+rm -f /tmp/qemu-$$-sdl-config.log
#if test "$sdl_static" = "no"; then
# echo "WARNING: cannot compile statically with SDL - qemu-fast won't have a graphical output"
#fi
@@ -638,29 +734,33 @@ config_h="config-host.h"
#echo "Creating $config_mak and $config_h"
+test -f $config_h && mv $config_h ${config_h}~
+
echo "# Automatically generated by configure - do not modify" > $config_mak
echo "# Configured with: $0 $@" >> $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 "bindir=\${prefix}$binsuffix" >> $config_mak
+echo "mandir=\${prefix}$mansuffix" >> $config_mak
+echo "datadir=\${prefix}$datasuffix" >> $config_mak
+echo "docdir=\${prefix}$docsuffix" >> $config_mak
+echo "#define CONFIG_QEMU_SHAREDIR \"$prefix$datasuffix\"" >> $config_h
echo "MAKE=$make" >> $config_mak
echo "INSTALL=$install" >> $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 "OS_CFLAGS=$OS_CFLAGS" >> $config_mak
+echo "OS_LDFLAGS=$OS_LDFLAGS" >> $config_mak
+echo "VL_OS_LDFLAGS=$VL_OS_LDFLAGS" >> $config_mak
+echo "ARCH_CFLAGS=$ARCH_CFLAGS" >> $config_mak
+echo "ARCH_LDFLAGS=$ARCH_LDFLAGS" >> $config_mak
echo "CFLAGS=$CFLAGS" >> $config_mak
echo "LDFLAGS=$LDFLAGS" >> $config_mak
echo "EXESUF=$EXESUF" >> $config_mak
+echo "AIOLIBS=$AIOLIBS" >> $config_mak
if test "$cpu" = "i386" ; then
echo "ARCH=i386" >> $config_mak
echo "#define HOST_I386 1" >> $config_h
@@ -679,6 +779,9 @@ elif test "$cpu" = "powerpc" ; then
elif test "$cpu" = "mips" ; then
echo "ARCH=mips" >> $config_mak
echo "#define HOST_MIPS 1" >> $config_h
+elif test "$cpu" = "mips64" ; then
+ echo "ARCH=mips64" >> $config_mak
+ echo "#define HOST_MIPS64 1" >> $config_h
elif test "$cpu" = "s390" ; then
echo "ARCH=s390" >> $config_mak
echo "#define HOST_S390 1" >> $config_h
@@ -698,7 +801,7 @@ elif test "$cpu" = "m68k" ; then
echo "ARCH=m68k" >> $config_mak
echo "#define HOST_M68K 1" >> $config_h
else
- echo "Unsupported CPU"
+ echo "Unsupported CPU = $cpu"
exit 1
fi
if test "$bigendian" = "yes" ; then
@@ -709,8 +812,14 @@ echo "#define HOST_LONG_BITS $hostlongbits" >> $config_h
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
+else
+ cat > $TMPC << EOF
+#include <byteswap.h>
+int main(void) { return bswap_32(0); }
+EOF
+ if $cc -o $TMPE $TMPC 2> /dev/null ; then
+ echo "#define HAVE_BYTESWAP_H 1" >> $config_h
+ fi
fi
if test "$darwin" = "yes" ; then
echo "CONFIG_DARWIN=yes" >> $config_mak
@@ -719,6 +828,14 @@ fi
if test "$solaris" = "yes" ; then
echo "CONFIG_SOLARIS=yes" >> $config_mak
echo "#define HOST_SOLARIS $solarisrev" >> $config_h
+ if test "$needs_libsunmath" = "yes" ; then
+ echo "NEEDS_LIBSUNMATH=yes" >> $config_mak
+ echo "#define NEEDS_LIBSUNMATH 1" >> $config_h
+ fi
+fi
+if test -n "$sparc_cpu"; then
+ echo "CONFIG__sparc_${sparc_cpu}__=yes" >> $config_mak
+ echo "#define __sparc_${sparc_cpu}__ 1" >> $config_h
fi
if test "$gdbstub" = "yes" ; then
echo "CONFIG_GDBSTUB=yes" >> $config_mak
@@ -765,6 +882,12 @@ if test "$fmod" = "yes" ; then
echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak
echo "#define CONFIG_FMOD 1" >> $config_h
fi
+if test "$vnc_tls" = "yes" ; then
+ echo "CONFIG_VNC_TLS=yes" >> $config_mak
+ echo "CONFIG_VNC_TLS_CFLAGS=$vnc_tls_cflags" >> $config_mak
+ echo "CONFIG_VNC_TLS_LIBS=$vnc_tls_libs" >> $config_mak
+ echo "#define CONFIG_VNC_TLS 1" >> $config_h
+fi
qemu_version=`head $source_path/VERSION`
echo "VERSION=$qemu_version" >>$config_mak
echo "#define QEMU_VERSION \"$qemu_version\"" >> $config_h
@@ -787,6 +910,14 @@ fi
echo "#define CONFIG_UNAME_RELEASE \"$uname_release\"" >> $config_h
+tools=
+if test `expr "$target_list" : ".*softmmu.*"` != 0 ; then
+ tools="qemu-img\$(EXESUF) $tools"
+fi
+echo "TOOLS=$tools" >> $config_mak
+
+test -f ${config_h}~ && cmp -s $config_h ${config_h}~ && mv ${config_h}~ $config_h
+
for target in $target_list; do
target_dir="$target"
config_mak=$target_dir/config.mak
@@ -798,27 +929,33 @@ target_bigendian="no"
[ "$target_cpu" = "sparc64" ] && target_bigendian=yes
[ "$target_cpu" = "ppc" ] && target_bigendian=yes
[ "$target_cpu" = "ppc64" ] && target_bigendian=yes
+[ "$target_cpu" = "ppcemb" ] && target_bigendian=yes
[ "$target_cpu" = "mips" ] && target_bigendian=yes
+[ "$target_cpu" = "mipsn32" ] && target_bigendian=yes
+[ "$target_cpu" = "mips64" ] && target_bigendian=yes
[ "$target_cpu" = "sh4eb" ] && target_bigendian=yes
[ "$target_cpu" = "m68k" ] && target_bigendian=yes
target_softmmu="no"
-if expr $target : '.*-softmmu' > /dev/null ; then
- target_softmmu="yes"
-fi
target_user_only="no"
-if expr $target : '.*-user' > /dev/null ; then
- target_user_only="yes"
-fi
-
target_linux_user="no"
-if expr $target : '.*-linux-user' > /dev/null ; then
- target_linux_user="yes"
-fi
-
target_darwin_user="no"
-if expr $target : '.*-darwin-user' > /dev/null ; then
- target_darwin_user="yes"
-fi
+case "$target" in
+ ${target_cpu}-softmmu)
+ target_softmmu="yes"
+ ;;
+ ${target_cpu}-linux-user)
+ target_user_only="yes"
+ target_linux_user="yes"
+ ;;
+ ${target_cpu}-darwin-user)
+ target_user_only="yes"
+ target_darwin_user="yes"
+ ;;
+ *)
+ echo "ERROR: Target '$target' not recognised"
+ exit 1
+ ;;
+esac
if test "$target_user_only" = "no" -a "$check_gfx" = "yes" \
-a "$sdl" = "no" -a "$cocoa" = "no" ; then
@@ -830,6 +967,8 @@ fi
#echo "Creating $config_mak, $config_h and $target_dir/Makefile"
+test -f $config_h && mv $config_h ${config_h}~
+
mkdir -p $target_dir
mkdir -p $target_dir/fpu
if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" ; then
@@ -887,6 +1026,11 @@ elif test "$target_cpu" = "ppc64" ; then
echo "#define TARGET_ARCH \"ppc64\"" >> $config_h
echo "#define TARGET_PPC 1" >> $config_h
echo "#define TARGET_PPC64 1" >> $config_h
+elif test "$target_cpu" = "ppcemb" ; then
+ echo "TARGET_ARCH=ppcemb" >> $config_mak
+ echo "#define TARGET_ARCH \"ppcemb\"" >> $config_h
+ echo "#define TARGET_PPC 1" >> $config_h
+ echo "#define TARGET_PPCEMB 1" >> $config_h
elif test "$target_cpu" = "x86_64" ; then
echo "TARGET_ARCH=x86_64" >> $config_mak
echo "#define TARGET_ARCH \"x86_64\"" >> $config_h
@@ -899,8 +1043,16 @@ elif test "$target_cpu" = "mips" -o "$target_cpu" = "mipsel" ; then
echo "TARGET_ARCH=mips" >> $config_mak
echo "#define TARGET_ARCH \"mips\"" >> $config_h
echo "#define TARGET_MIPS 1" >> $config_h
- echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
- echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
+elif test "$target_cpu" = "mipsn32" -o "$target_cpu" = "mipsn32el" ; then
+ echo "TARGET_ARCH=mipsn32" >> $config_mak
+ echo "#define TARGET_ARCH \"mipsn32\"" >> $config_h
+ echo "#define TARGET_MIPS 1" >> $config_h
+ echo "#define TARGET_MIPSN32 1" >> $config_h
+elif test "$target_cpu" = "mips64" -o "$target_cpu" = "mips64el" ; then
+ echo "TARGET_ARCH=mips64" >> $config_mak
+ echo "#define TARGET_ARCH \"mips64\"" >> $config_h
+ echo "#define TARGET_MIPS 1" >> $config_h
+ echo "#define TARGET_MIPS64 1" >> $config_h
elif test "$target_cpu" = "sh4" -o "$target_cpu" = "sh4eb" ; then
echo "TARGET_ARCH=sh4" >> $config_mak
echo "#define TARGET_ARCH \"sh4\"" >> $config_h
@@ -911,6 +1063,10 @@ elif test "$target_cpu" = "m68k" ; then
echo "#define TARGET_ARCH \"m68k\"" >> $config_h
echo "#define TARGET_M68K 1" >> $config_h
bflt="yes"
+elif test "$target_cpu" = "alpha" ; then
+ echo "TARGET_ARCH=alpha" >> $config_mak
+ echo "#define TARGET_ARCH \"alpha\"" >> $config_h
+ echo "#define TARGET_ALPHA 1" >> $config_h
else
echo "Unsupported target CPU"
exit 1
@@ -936,7 +1092,7 @@ if test "$target_darwin_user" = "yes" ; then
echo "#define CONFIG_DARWIN_USER 1" >> $config_h
fi
-if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then
+if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k" -o "$target_cpu" = "mips" -o "$target_cpu" = "mipsel" -o "$target_cpu" = "mipsn32" -o "$target_cpu" = "mipsn32el" -o "$target_cpu" = "mips64" -o "$target_cpu" = "mips64el"; then
echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
fi
@@ -973,6 +1129,8 @@ if test "$cocoa" = "yes" ; then
echo "CONFIG_COCOA=yes" >> $config_mak
fi
+test -f ${config_h}~ && cmp -s $config_h ${config_h}~ && mv ${config_h}~ $config_h
+
done # for target in $targets
# build tree in object directory if source path is different from current one
diff --git a/console.c b/console.c
index 2b3cd669d..ff725c2e6 100644
--- a/console.c
+++ b/console.c
@@ -1,8 +1,8 @@
/*
* QEMU graphical console
- *
+ *
* 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
@@ -104,10 +104,16 @@ int qemu_fifo_read(QEMUFIFO *f, uint8_t *buf, int len1)
return len1;
}
+typedef enum {
+ GRAPHIC_CONSOLE,
+ TEXT_CONSOLE,
+ TEXT_CONSOLE_FIXED_SIZE
+} console_type_t;
+
/* ??? This is mis-named.
It is used for both text and graphical consoles. */
struct TextConsole {
- int text_console; /* true if text console */
+ console_type_t console_type;
DisplayState *ds;
/* Graphic console state. */
vga_hw_update_ptr hw_update;
@@ -174,8 +180,8 @@ static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
r = (rgba >> 16) & 0xff;
g = (rgba >> 8) & 0xff;
b = (rgba) & 0xff;
- color = (rgb_to_index[r] * 6 * 6) +
- (rgb_to_index[g] * 6) +
+ color = (rgb_to_index[r] * 6 * 6) +
+ (rgb_to_index[g] * 6) +
(rgb_to_index[b]);
break;
#endif
@@ -199,14 +205,14 @@ static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
return color;
}
-static void vga_fill_rect (DisplayState *ds,
+static void vga_fill_rect (DisplayState *ds,
int posx, int posy, int width, int height, uint32_t color)
{
uint8_t *d, *d1;
int x, y, bpp;
-
+
bpp = (ds->depth + 7) >> 3;
- d1 = ds->data +
+ d1 = ds->data +
ds->linesize * posy + bpp * posx;
for (y = 0; y < height; y++) {
d = d1;
@@ -244,9 +250,9 @@ static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w,
bpp = (ds->depth + 7) >> 3;
wb = w * bpp;
if (yd <= ys) {
- s = ds->data +
+ s = ds->data +
ds->linesize * ys + bpp * xs;
- d = ds->data +
+ d = ds->data +
ds->linesize * yd + bpp * xd;
for (y = 0; y < h; y++) {
memmove(d, s, wb);
@@ -254,9 +260,9 @@ static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w,
s += ds->linesize;
}
} else {
- s = ds->data +
+ s = ds->data +
ds->linesize * (ys + h - 1) + bpp * xs;
- d = ds->data +
+ d = ds->data +
ds->linesize * (yd + h - 1) + bpp * xd;
for (y = 0; y < h; y++) {
memmove(d, s, wb);
@@ -399,7 +405,7 @@ static void console_print_text_attributes(TextAttributes *t_attrib, char ch)
}
#endif
-static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
+static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
TextAttributes *t_attrib)
{
uint8_t *d;
@@ -422,7 +428,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
}
bpp = (ds->depth + 7) >> 3;
- d = ds->data +
+ d = ds->data +
ds->linesize * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
linesize = ds->linesize;
font_ptr = vgafont16 + FONT_HEIGHT * ch;
@@ -519,9 +525,9 @@ static void update_xy(TextConsole *s, int x, int y)
y2 += s->total_height;
if (y2 < s->height) {
c = &s->cells[y1 * s->width + x];
- vga_putcharxy(s->ds, x, y2, c->ch,
+ vga_putcharxy(s->ds, x, y2, c->ch,
&(c->t_attrib));
- dpy_update(s->ds, x * FONT_WIDTH, y2 * FONT_HEIGHT,
+ dpy_update(s->ds, x * FONT_WIDTH, y2 * FONT_HEIGHT,
FONT_WIDTH, FONT_HEIGHT);
}
}
@@ -533,21 +539,24 @@ static void console_show_cursor(TextConsole *s, int show)
int y, y1;
if (s == active_console) {
+ int x = s->x;
+ if (x >= s->width) {
+ x = s->width - 1;
+ }
y1 = (s->y_base + s->y) % s->total_height;
y = y1 - s->y_displayed;
if (y < 0)
y += s->total_height;
if (y < s->height) {
- c = &s->cells[y1 * s->width + s->x];
+ c = &s->cells[y1 * s->width + x];
if (show) {
TextAttributes t_attrib = s->t_attrib_default;
t_attrib.invers = !(t_attrib.invers); /* invert fg and bg */
- vga_putcharxy(s->ds, s->x, y, c->ch, &t_attrib);
+ vga_putcharxy(s->ds, x, y, c->ch, &t_attrib);
} else {
- vga_putcharxy(s->ds, s->x, y, c->ch,
- &(c->t_attrib));
+ vga_putcharxy(s->ds, x, y, c->ch, &(c->t_attrib));
}
- dpy_update(s->ds, s->x * FONT_WIDTH, y * FONT_HEIGHT,
+ dpy_update(s->ds, x * FONT_WIDTH, y * FONT_HEIGHT,
FONT_WIDTH, FONT_HEIGHT);
}
}
@@ -558,7 +567,7 @@ static void console_refresh(TextConsole *s)
TextCell *c;
int x, y, y1;
- if (s != active_console)
+ if (s != active_console)
return;
vga_fill_rect(s->ds, 0, 0, s->ds->width, s->ds->height,
@@ -567,7 +576,7 @@ static void console_refresh(TextConsole *s)
for(y = 0; y < s->height; y++) {
c = s->cells + y1 * s->width;
for(x = 0; x < s->width; x++) {
- vga_putcharxy(s->ds, x, y, c->ch,
+ vga_putcharxy(s->ds, x, y, c->ch,
&(c->t_attrib));
c++;
}
@@ -582,9 +591,9 @@ static void console_scroll(int ydelta)
{
TextConsole *s;
int i, y1;
-
+
s = active_console;
- if (!s || !s->text_console)
+ if (!s || (s->console_type == GRAPHIC_CONSOLE))
return;
if (ydelta > 0) {
@@ -637,13 +646,13 @@ static void console_put_lf(TextConsole *s)
c++;
}
if (s == active_console && s->y_displayed == s->y_base) {
- vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0,
- s->width * FONT_WIDTH,
+ vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0,
+ s->width * FONT_WIDTH,
(s->height - 1) * FONT_HEIGHT);
vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT,
- s->width * FONT_WIDTH, FONT_HEIGHT,
+ s->width * FONT_WIDTH, FONT_HEIGHT,
color_table[0][s->t_attrib_default.bgcol]);
- dpy_update(s->ds, 0, 0,
+ dpy_update(s->ds, 0, 0,
s->width * FONT_WIDTH, s->height * FONT_HEIGHT);
}
}
@@ -772,7 +781,7 @@ static void console_putchar(TextConsole *s, int ch)
console_put_lf(s);
break;
case '\b': /* backspace */
- if (s->x > 0)
+ if (s->x > 0)
s->x--;
break;
case '\t': /* tabspace */
@@ -796,8 +805,10 @@ static void console_putchar(TextConsole *s, int ch)
s->state = TTY_STATE_ESC;
break;
default:
- if (s->x >= s->width - 1) {
- break;
+ if (s->x >= s->width) {
+ /* line wrap */
+ s->x = 0;
+ console_put_lf(s);
}
y1 = (s->y_base + s->y) % s->total_height;
c = &s->cells[y1 * s->width + s->x];
@@ -805,12 +816,6 @@ static void console_putchar(TextConsole *s, int ch)
c->t_attrib = s->t_attrib;
update_xy(s, s->x, s->y);
s->x++;
-#if 0 /* line wrap disabled */
- if (s->x >= s->width) {
- s->x = 0;
- console_put_lf(s);
- }
-#endif
break;
}
break;
@@ -827,7 +832,7 @@ static void console_putchar(TextConsole *s, int ch)
case TTY_STATE_CSI: /* handle escape sequence parameters */
if (ch >= '0' && ch <= '9') {
if (s->nb_esc_params < MAX_ESC_PARAMS) {
- s->esc_params[s->nb_esc_params] =
+ s->esc_params[s->nb_esc_params] =
s->esc_params[s->nb_esc_params] * 10 + ch - '0';
}
} else {
@@ -991,13 +996,17 @@ void console_select(unsigned int index)
s = consoles[index];
if (s) {
active_console = s;
- if (s->text_console) {
+ if (s->console_type != GRAPHIC_CONSOLE) {
if (s->g_width != s->ds->width ||
s->g_height != s->ds->height) {
+ if (s->console_type == TEXT_CONSOLE_FIXED_SIZE) {
+ dpy_resize(s->ds, s->g_width, s->g_height);
+ } else {
s->g_width = s->ds->width;
s->g_height = s->ds->height;
text_console_resize(s);
}
+ }
console_refresh(s);
} else {
vga_hw_invalidate();
@@ -1038,7 +1047,7 @@ static void kbd_send_chars(void *opaque)
TextConsole *s = opaque;
int len;
uint8_t buf[16];
-
+
len = qemu_chr_can_read(s->chr);
if (len > s->out_fifo.count)
len = s->out_fifo.count;
@@ -1063,7 +1072,7 @@ void kbd_put_keysym(int keysym)
int c;
s = active_console;
- if (!s || !s->text_console)
+ if (!s || (s->console_type == GRAPHIC_CONSOLE))
return;
switch(keysym) {
@@ -1105,7 +1114,7 @@ void kbd_put_keysym(int keysym)
}
}
-static TextConsole *new_console(DisplayState *ds, int text)
+static TextConsole *new_console(DisplayState *ds, console_type_t console_type)
{
TextConsole *s;
int i;
@@ -1116,16 +1125,18 @@ static TextConsole *new_console(DisplayState *ds, int text)
if (!s) {
return NULL;
}
- if (!active_console || (active_console->text_console && !text))
+ if (!active_console || ((active_console->console_type != GRAPHIC_CONSOLE) &&
+ (console_type == GRAPHIC_CONSOLE))) {
active_console = s;
+ }
s->ds = ds;
- s->text_console = text;
- if (text) {
+ s->console_type = console_type;
+ if (console_type != GRAPHIC_CONSOLE) {
consoles[nb_consoles++] = s;
} else {
/* HACK: Put graphical consoles before text consoles. */
for (i = nb_consoles; i > 0; i--) {
- if (!consoles[i - 1]->text_console)
+ if (consoles[i - 1]->console_type == GRAPHIC_CONSOLE)
break;
consoles[i] = consoles[i - 1];
}
@@ -1141,7 +1152,7 @@ TextConsole *graphic_console_init(DisplayState *ds, vga_hw_update_ptr update,
{
TextConsole *s;
- s = new_console(ds, 0);
+ s = new_console(ds, GRAPHIC_CONSOLE);
if (!s)
return NULL;
s->hw_update = update;
@@ -1153,20 +1164,22 @@ TextConsole *graphic_console_init(DisplayState *ds, vga_hw_update_ptr update,
int is_graphic_console(void)
{
- return !active_console->text_console;
+ return active_console->console_type == GRAPHIC_CONSOLE;
}
-CharDriverState *text_console_init(DisplayState *ds)
+CharDriverState *text_console_init(DisplayState *ds, const char *p)
{
CharDriverState *chr;
TextConsole *s;
int i,j;
+ unsigned width;
+ unsigned height;
static int color_inited;
chr = qemu_mallocz(sizeof(CharDriverState));
if (!chr)
return NULL;
- s = new_console(ds, 1);
+ s = new_console(ds, (p == 0) ? TEXT_CONSOLE : TEXT_CONSOLE_FIXED_SIZE);
if (!s) {
free(chr);
return NULL;
@@ -1179,12 +1192,12 @@ CharDriverState *text_console_init(DisplayState *ds)
s->out_fifo.buf = s->out_fifo_buf;
s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
-
+
if (!color_inited) {
color_inited = 1;
for(j = 0; j < 2; j++) {
for(i = 0; i < 8; i++) {
- color_table[j][i] = col_expand(s->ds,
+ color_table[j][i] = col_expand(s->ds,
vga_get_color(s->ds, color_table_rgb[j][i]));
}
}
@@ -1194,8 +1207,25 @@ CharDriverState *text_console_init(DisplayState *ds)
s->total_height = DEFAULT_BACKSCROLL;
s->x = 0;
s->y = 0;
- s->g_width = s->ds->width;
- s->g_height = s->ds->height;
+ width = s->ds->width;
+ height = s->ds->height;
+ if (p != 0) {
+ width = strtoul(p, (char **)&p, 10);
+ if (*p == 'C') {
+ p++;
+ width *= FONT_WIDTH;
+ }
+ if (*p == 'x') {
+ p++;
+ height = strtoul(p, (char **)&p, 10);
+ if (*p == 'C') {
+ p++;
+ height *= FONT_HEIGHT;
+ }
+ }
+ }
+ s->g_width = width;
+ s->g_height = height;
/* Set text attribute defaults */
s->t_attrib_default.bold = 0;
diff --git a/cpu-all.h b/cpu-all.h
index ed5355319..4e200928f 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -1,6 +1,6 @@
/*
* defines common to all virtual CPUs
- *
+ *
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
@@ -20,20 +20,20 @@
#ifndef CPU_ALL_H
#define CPU_ALL_H
-#if defined(__arm__) || defined(__sparc__)
+#if defined(__arm__) || defined(__sparc__) || defined(__mips__)
#define WORDS_ALIGNED
#endif
-/* some important defines:
- *
+/* 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
*/
@@ -147,7 +147,7 @@ typedef union {
* type is:
* (empty): integer access
* f : float access
- *
+ *
* sign is:
* (empty): for floats or 32 bit size
* u : unsigned
@@ -158,7 +158,7 @@ typedef union {
* 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)
@@ -621,7 +621,7 @@ static inline void stfq_be_p(void *ptr, float64 v)
#define stfq_raw(p, v) stfq_p(saddr((p)), v)
-#if defined(CONFIG_USER_ONLY)
+#if defined(CONFIG_USER_ONLY)
/* if user mode, no other memory access functions */
#define ldub(p) ldub_raw(p)
@@ -644,12 +644,14 @@ static inline void stfq_be_p(void *ptr, float64 v)
#define lduw_code(p) lduw_raw(p)
#define ldsw_code(p) ldsw_raw(p)
#define ldl_code(p) ldl_raw(p)
+#define ldq_code(p) ldq_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 ldq_kernel(p) ldq_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)
@@ -683,82 +685,25 @@ extern unsigned long qemu_host_page_mask;
#define PAGE_VALID 0x0008
/* original state of the write flag (used when tracking self-modifying
code */
-#define PAGE_WRITE_ORG 0x0010
+#define PAGE_WRITE_ORG 0x0010
void page_dump(FILE *f);
int page_get_flags(target_ulong address);
void page_set_flags(target_ulong start, target_ulong end, int flags);
void page_unprotect_range(target_ulong data, target_ulong data_size);
-#define SINGLE_CPU_DEFINES
-#ifdef SINGLE_CPU_DEFINES
-
-#if defined(TARGET_I386)
-
-#define CPUState CPUX86State
-#define cpu_init cpu_x86_init
-#define cpu_exec cpu_x86_exec
-#define cpu_gen_code cpu_x86_gen_code
-#define cpu_signal_handler cpu_x86_signal_handler
-
-#elif defined(TARGET_ARM)
-
-#define CPUState CPUARMState
-#define cpu_init cpu_arm_init
-#define cpu_exec cpu_arm_exec
-#define cpu_gen_code cpu_arm_gen_code
-#define cpu_signal_handler cpu_arm_signal_handler
-
-#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
-
-#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
-
-#elif defined(TARGET_M68K)
-#define CPUState CPUM68KState
-#define cpu_init cpu_m68k_init
-#define cpu_exec cpu_m68k_exec
-#define cpu_gen_code cpu_m68k_gen_code
-#define cpu_signal_handler cpu_m68k_signal_handler
-
-#elif defined(TARGET_MIPS)
-#define CPUState CPUMIPSState
-#define cpu_init cpu_mips_init
-#define cpu_exec cpu_mips_exec
-#define cpu_gen_code cpu_mips_gen_code
-#define cpu_signal_handler cpu_mips_signal_handler
-
-#elif defined(TARGET_SH4)
-#define CPUState CPUSH4State
-#define cpu_init cpu_sh4_init
-#define cpu_exec cpu_sh4_exec
-#define cpu_gen_code cpu_sh4_gen_code
-#define cpu_signal_handler cpu_sh4_signal_handler
-
-#else
-
-#error unsupported target CPU
-
-#endif
-
-#endif /* SINGLE_CPU_DEFINES */
+CPUState *cpu_copy(CPUState *env);
-void cpu_dump_state(CPUState *env, FILE *f,
+void cpu_dump_state(CPUState *env, FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
int flags);
+void cpu_dump_statistics (CPUState *env, FILE *f,
+ int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+ int flags);
-void cpu_abort(CPUState *env, const char *fmt, ...);
+void cpu_abort(CPUState *env, const char *fmt, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)))
+ __attribute__ ((__noreturn__));
extern CPUState *first_cpu;
extern CPUState *cpu_single_env;
extern int code_copy_enabled;
@@ -770,10 +715,14 @@ extern int code_copy_enabled;
#define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */
#define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */
#define CPU_INTERRUPT_SMI 0x40 /* (x86 only) SMI interrupt pending */
+#define CPU_INTERRUPT_DEBUG 0x80 /* Debug event occured. */
+#define CPU_INTERRUPT_VIRQ 0x100 /* virtual interrupt pending. */
void cpu_interrupt(CPUState *s, int mask);
void cpu_reset_interrupt(CPUState *env, int mask);
+int cpu_watchpoint_insert(CPUState *env, target_ulong addr);
+int cpu_watchpoint_remove(CPUState *env, target_ulong addr);
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);
@@ -782,9 +731,9 @@ 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);
+target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
-#define CPU_LOG_TB_OUT_ASM (1 << 0)
+#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)
@@ -840,14 +789,17 @@ extern uint8_t *phys_ram_dirty;
exception, the write memory callback gets the ram offset instead of
the physical address */
#define IO_MEM_ROMD (1)
+#define IO_MEM_SUBPAGE (2)
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,
+void cpu_register_physical_memory(target_phys_addr_t start_addr,
unsigned long size,
unsigned long phys_offset);
uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr);
+ram_addr_t qemu_ram_alloc(unsigned int size);
+void qemu_ram_free(ram_addr_t addr);
int cpu_register_io_memory(int io_index,
CPUReadMemoryFunc **mem_read,
CPUWriteMemoryFunc **mem_write,
@@ -857,12 +809,12 @@ CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index);
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,
+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,
+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);
@@ -872,14 +824,15 @@ uint32_t lduw_phys(target_phys_addr_t addr);
uint32_t ldl_phys(target_phys_addr_t addr);
uint64_t ldq_phys(target_phys_addr_t addr);
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
+void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val);
void stb_phys(target_phys_addr_t addr, uint32_t val);
void stw_phys(target_phys_addr_t addr, uint32_t val);
void stl_phys(target_phys_addr_t addr, uint32_t val);
void stq_phys(target_phys_addr_t addr, uint64_t val);
-void cpu_physical_memory_write_rom(target_phys_addr_t addr,
+void cpu_physical_memory_write_rom(target_phys_addr_t addr,
const uint8_t *buf, int len);
-int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
+int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
uint8_t *buf, int len, int is_write);
#define VGA_DIRTY_FLAG 0x01
@@ -891,7 +844,7 @@ static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
return phys_ram_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
}
-static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
+static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
int dirty_flags)
{
return phys_ram_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
@@ -914,14 +867,14 @@ void dump_exec_info(FILE *f,
#if defined(__powerpc__)
-static inline uint32_t get_tbl(void)
+static inline uint32_t get_tbl(void)
{
uint32_t tbl;
asm volatile("mftb %0" : "=r" (tbl));
return tbl;
}
-static inline uint32_t get_tbu(void)
+static inline uint32_t get_tbu(void)
{
uint32_t tbl;
asm volatile("mftbu %0" : "=r" (tbl));
@@ -980,7 +933,7 @@ static inline int64_t cpu_get_real_ticks(void)
return val;
}
-#elif defined(__sparc_v9__)
+#elif defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
static inline int64_t cpu_get_real_ticks (void)
{
@@ -1001,10 +954,31 @@ static inline int64_t cpu_get_real_ticks (void)
return rval.i64;
#endif
}
+
+#elif defined(__mips__)
+
+static inline int64_t cpu_get_real_ticks(void)
+{
+#if __mips_isa_rev >= 2
+ uint32_t count;
+ static uint32_t cyc_per_count = 0;
+
+ if (!cyc_per_count)
+ __asm__ __volatile__("rdhwr %0, $3" : "=r" (cyc_per_count));
+
+ __asm__ __volatile__("rdhwr %1, $2" : "=r" (count));
+ return (int64_t)(count * cyc_per_count);
+#else
+ /* FIXME */
+ static int64_t ticks = 0;
+ return ticks++;
+#endif
+}
+
#else
/* The host CPU doesn't have an easily accessible cycle counter.
- Just return a monotonically increasing vlue. This will be totally wrong,
- but hopefully better than nothing. */
+ Just return a monotonically increasing value. This will be
+ totally wrong, but hopefully better than nothing. */
static inline int64_t cpu_get_real_ticks (void)
{
static int64_t ticks = 0;
diff --git a/cpu-defs.h b/cpu-defs.h
index 0b49c8991..915877617 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -1,6 +1,6 @@
/*
* common defines for all CPUs
- *
+ *
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
@@ -29,7 +29,7 @@
#error TARGET_LONG_BITS must be defined before including this header
#endif
-#ifndef TARGET_PHYS_ADDR_BITS
+#ifndef TARGET_PHYS_ADDR_BITS
#if TARGET_LONG_BITS >= HOST_LONG_BITS
#define TARGET_PHYS_ADDR_BITS TARGET_LONG_BITS
#else
@@ -44,10 +44,14 @@
typedef int32_t target_long;
typedef uint32_t target_ulong;
#define TARGET_FMT_lx "%08x"
+#define TARGET_FMT_ld "%d"
+#define TARGET_FMT_lu "%u"
#elif TARGET_LONG_SIZE == 8
typedef int64_t target_long;
typedef uint64_t target_ulong;
#define TARGET_FMT_lx "%016" PRIx64
+#define TARGET_FMT_ld "%" PRId64
+#define TARGET_FMT_lu "%" PRIu64
#else
#error TARGET_LONG_SIZE undefined
#endif
@@ -60,8 +64,10 @@ typedef uint64_t target_ulong;
#if TARGET_PHYS_ADDR_BITS == 32
typedef uint32_t target_phys_addr_t;
+#define TARGET_FMT_plx "%08x"
#elif TARGET_PHYS_ADDR_BITS == 64
typedef uint64_t target_phys_addr_t;
+#define TARGET_FMT_plx "%016" PRIx64
#else
#error TARGET_PHYS_ADDR_BITS undefined
#endif
@@ -76,6 +82,7 @@ typedef unsigned long ram_addr_t;
#define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */
#define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */
#define MAX_BREAKPOINTS 32
+#define MAX_WATCHPOINTS 32
#define TB_JMP_CACHE_BITS 12
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
@@ -92,19 +99,28 @@ typedef unsigned long ram_addr_t;
#define CPU_TLB_SIZE (1 << CPU_TLB_BITS)
typedef struct CPUTLBEntry {
- /* bit 31 to TARGET_PAGE_BITS : virtual address
+ /* 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 addr_read;
- target_ulong addr_write;
- target_ulong addr_code;
+ target_ulong addr_read;
+ target_ulong addr_write;
+ target_ulong addr_code;
/* addend to virtual address to get physical address */
- target_phys_addr_t addend;
+ target_phys_addr_t addend;
} CPUTLBEntry;
+/* Alpha has 4 different running levels */
+#if defined(TARGET_ALPHA)
+#define NB_MMU_MODES 4
+#elif defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+#define NB_MMU_MODES 3
+#else
+#define NB_MMU_MODES 2
+#endif
+
#define CPU_COMMON \
struct TranslationBlock *current_tb; /* currently executing TB */ \
/* soft mmu support */ \
@@ -116,7 +132,7 @@ typedef struct CPUTLBEntry {
target_ulong mem_write_vaddr; /* target virtual addr at which the \
memory was written */ \
/* 0 = kernel, 1 = user */ \
- CPUTLBEntry tlb_table[2][CPU_TLB_SIZE]; \
+ CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \
\
/* from this point: preserved by CPU reset */ \
@@ -125,6 +141,13 @@ typedef struct CPUTLBEntry {
int nb_breakpoints; \
int singlestep_enabled; \
\
+ struct { \
+ target_ulong vaddr; \
+ target_phys_addr_t addend; \
+ } watchpoint[MAX_WATCHPOINTS]; \
+ int nb_watchpoints; \
+ int watchpoint_hit; \
+ \
void *next_cpu; /* next CPU sharing TB cache */ \
int cpu_index; /* CPU index (informative) */ \
/* user data */ \
diff --git a/cpu-exec.c b/cpu-exec.c
index 058688fc7..55758faef 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -1,6 +1,6 @@
/*
* i386 emulator main execution loop
- *
+ *
* Copyright (c) 2003-2005 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
@@ -40,13 +40,14 @@ int tb_invalidated_flag;
//#define DEBUG_EXEC
//#define DEBUG_SIGNAL
-#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K)
-/* XXX: unify with i386 target */
void cpu_loop_exit(void)
{
+ /* NOTE: the register at this point must be saved by hand because
+ longjmp restore them */
+ regs_to_env();
longjmp(env->jmp_env, 1);
}
-#endif
+
#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
#define reg_T2
#endif
@@ -54,7 +55,7 @@ void cpu_loop_exit(void)
/* 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)
+void cpu_resume_from_signal(CPUState *env1, void *puc)
{
#if !defined(CONFIG_SOFTMMU)
struct ucontext *uc = puc;
@@ -76,20 +77,20 @@ void cpu_resume_from_signal(CPUState *env1, void *puc)
static TranslationBlock *tb_find_slow(target_ulong pc,
target_ulong cs_base,
- unsigned int flags)
+ uint64_t flags)
{
TranslationBlock *tb, **ptb1;
int code_gen_size;
unsigned int h;
target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
uint8_t *tc_ptr;
-
+
spin_lock(&tb_lock);
tb_invalidated_flag = 0;
-
+
regs_to_env(); /* XXX: do it just before cpu_gen_code() */
-
+
/* find translated block using physical mappings */
phys_pc = get_phys_addr_code(env, pc);
phys_page1 = phys_pc & TARGET_PAGE_MASK;
@@ -100,13 +101,13 @@ static TranslationBlock *tb_find_slow(target_ulong pc,
tb = *ptb1;
if (!tb)
goto not_found;
- if (tb->pc == pc &&
+ if (tb->pc == pc &&
tb->page_addr[0] == phys_page1 &&
- tb->cs_base == cs_base &&
+ tb->cs_base == cs_base &&
tb->flags == flags) {
/* check next page if needed */
if (tb->page_addr[1] != -1) {
- virt_page2 = (pc & TARGET_PAGE_MASK) +
+ virt_page2 = (pc & TARGET_PAGE_MASK) +
TARGET_PAGE_SIZE;
phys_page2 = get_phys_addr_code(env, virt_page2);
if (tb->page_addr[1] == phys_page2)
@@ -134,7 +135,7 @@ static TranslationBlock *tb_find_slow(target_ulong pc,
tb->flags = flags;
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 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
phys_page2 = -1;
@@ -142,7 +143,7 @@ static TranslationBlock *tb_find_slow(target_ulong pc,
phys_page2 = get_phys_addr_code(env, virt_page2);
}
tb_link_phys(tb, phys_pc, phys_page2);
-
+
found:
/* we add the TB in the virtual pc hash table */
env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
@@ -154,7 +155,7 @@ static inline TranslationBlock *tb_find_fast(void)
{
TranslationBlock *tb;
target_ulong cs_base, pc;
- unsigned int flags;
+ uint64_t flags;
/* we record a subset of the CPU state. It will
always be the same before a given translated block
@@ -162,6 +163,7 @@ static inline TranslationBlock *tb_find_fast(void)
#if defined(TARGET_I386)
flags = env->hflags;
flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
+ flags |= env->intercept;
cs_base = env->segs[R_CS].base;
pc = cs_base + env->eip;
#elif defined(TARGET_ARM)
@@ -179,29 +181,35 @@ static inline TranslationBlock *tb_find_fast(void)
flags = (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
| (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
#else
- // FPU enable . MMU enabled . MMU no-fault . Supervisor
- flags = (env->psref << 3) | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
+ // FPU enable . MMU Boot . MMU enabled . MMU no-fault . Supervisor
+ flags = (env->psref << 4) | (((env->mmuregs[0] & MMU_BM) >> 14) << 3)
+ | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1)
| env->psrs;
#endif
cs_base = env->npc;
pc = env->pc;
#elif defined(TARGET_PPC)
- flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) |
- (msr_se << MSR_SE) | (msr_le << MSR_LE);
+ flags = env->hflags;
cs_base = 0;
pc = env->nip;
#elif defined(TARGET_MIPS)
flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
cs_base = 0;
- pc = env->PC;
+ pc = env->PC[env->current_tc];
#elif defined(TARGET_M68K)
- flags = env->fpcr & M68K_FPCR_PREC;
+ flags = (env->fpcr & M68K_FPCR_PREC) /* Bit 6 */
+ | (env->sr & SR_S) /* Bit 13 */
+ | ((env->macsr >> 4) & 0xf); /* Bits 0-3 */
cs_base = 0;
pc = env->pc;
#elif defined(TARGET_SH4)
flags = env->sr & (SR_MD | SR_RB);
cs_base = 0; /* XXXXX */
pc = env->pc;
+#elif defined(TARGET_ALPHA)
+ flags = env->ps;
+ cs_base = 0;
+ pc = env->pc;
#else
#error unsupported CPU
#endif
@@ -242,59 +250,10 @@ int cpu_exec(CPUState *env1)
TranslationBlock *tb;
uint8_t *tc_ptr;
-#if defined(TARGET_I386)
- /* handle exit of HALTED state */
- if (env1->hflags & HF_HALTED_MASK) {
- /* disable halt condition */
- if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env1->eflags & IF_MASK)) {
- env1->hflags &= ~HF_HALTED_MASK;
- } else {
- return EXCP_HALTED;
- }
- }
-#elif defined(TARGET_PPC)
- if (env1->halted) {
- if (env1->msr[MSR_EE] &&
- (env1->interrupt_request &
- (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER))) {
- env1->halted = 0;
- } else {
- return EXCP_HALTED;
- }
- }
-#elif defined(TARGET_SPARC)
- if (env1->halted) {
- if ((env1->interrupt_request & CPU_INTERRUPT_HARD) &&
- (env1->psret != 0)) {
- env1->halted = 0;
- } else {
- return EXCP_HALTED;
- }
- }
-#elif defined(TARGET_ARM)
- if (env1->halted) {
- /* An interrupt wakes the CPU even if the I and F CPSR bits are
- set. */
- if (env1->interrupt_request
- & (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD)) {
- env1->halted = 0;
- } else {
- return EXCP_HALTED;
- }
- }
-#elif defined(TARGET_MIPS)
- if (env1->halted) {
- if (env1->interrupt_request &
- (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER)) {
- env1->halted = 0;
- } else {
- return EXCP_HALTED;
- }
- }
-#endif
+ if (cpu_halted(env1) == EXCP_HALTED)
+ return EXCP_HALTED;
- cpu_single_env = env1;
+ cpu_single_env = env1;
/* first we save global registers */
#define SAVE_HOST_REGS 1
@@ -305,23 +264,24 @@ int cpu_exec(CPUState *env1)
asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
#endif
-#if defined(TARGET_I386)
env_to_regs();
+#if defined(TARGET_I386)
/* put eflags in CPU temporary format */
CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
DF = 1 - (2 * ((env->eflags >> 10) & 1));
CC_OP = CC_OP_EFLAGS;
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-#elif defined(TARGET_ARM)
#elif defined(TARGET_SPARC)
#if defined(reg_REGWPTR)
saved_regwptr = REGWPTR;
#endif
-#elif defined(TARGET_PPC)
#elif defined(TARGET_M68K)
env->cc_op = CC_OP_FLAGS;
env->cc_dest = env->sr & 0xf;
env->cc_x = (env->sr >> 4) & 1;
+#elif defined(TARGET_ALPHA)
+#elif defined(TARGET_ARM)
+#elif defined(TARGET_PPC)
#elif defined(TARGET_MIPS)
#elif defined(TARGET_SH4)
/* XXXXX */
@@ -345,9 +305,9 @@ int cpu_exec(CPUState *env1)
which will be handled outside the cpu execution
loop */
#if defined(TARGET_I386)
- do_interrupt_user(env->exception_index,
- env->exception_is_int,
- env->error_code,
+ do_interrupt_user(env->exception_index,
+ env->exception_is_int,
+ env->error_code,
env->exception_next_eip);
#endif
ret = env->exception_index;
@@ -357,10 +317,12 @@ int cpu_exec(CPUState *env1)
/* simulate a real cpu exception. On i386, it can
trigger new exceptions, but we do not handle
double or triple faults yet. */
- do_interrupt(env->exception_index,
- env->exception_is_int,
- env->error_code,
+ do_interrupt(env->exception_index,
+ env->exception_is_int,
+ env->error_code,
env->exception_next_eip, 0);
+ /* successfully delivered */
+ env->old_exception = -1;
#elif defined(TARGET_PPC)
do_interrupt(env);
#elif defined(TARGET_MIPS)
@@ -371,10 +333,14 @@ int cpu_exec(CPUState *env1)
do_interrupt(env);
#elif defined(TARGET_SH4)
do_interrupt(env);
+#elif defined(TARGET_ALPHA)
+ do_interrupt(env);
+#elif defined(TARGET_M68K)
+ do_interrupt(0);
#endif
}
env->exception_index = -1;
- }
+ }
#ifdef USE_KQEMU
if (kqemu_is_ok(env) && env->interrupt_request == 0) {
int ret;
@@ -404,14 +370,33 @@ int cpu_exec(CPUState *env1)
T0 = 0; /* force lookup of first TB */
for(;;) {
#if defined(__sparc__) && !defined(HOST_SOLARIS)
- /* g1 can be modified by some libc? functions */
+ /* g1 can be modified by some libc? functions */
tmp_T0 = T0;
-#endif
+#endif
interrupt_request = env->interrupt_request;
- if (__builtin_expect(interrupt_request, 0)) {
+ if (__builtin_expect(interrupt_request, 0)
+#if defined(TARGET_I386)
+ && env->hflags & HF_GIF_MASK
+#endif
+ ) {
+ if (interrupt_request & CPU_INTERRUPT_DEBUG) {
+ env->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
+ env->exception_index = EXCP_DEBUG;
+ cpu_loop_exit();
+ }
+#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_MIPS) || \
+ defined(TARGET_PPC) || defined(TARGET_ALPHA)
+ if (interrupt_request & CPU_INTERRUPT_HALT) {
+ env->interrupt_request &= ~CPU_INTERRUPT_HALT;
+ env->halted = 1;
+ env->exception_index = EXCP_HLT;
+ cpu_loop_exit();
+ }
+#endif
#if defined(TARGET_I386)
if ((interrupt_request & CPU_INTERRUPT_SMI) &&
!(env->hflags & HF_SMM_MASK)) {
+ svm_check_intercept(SVM_EXIT_SMI);
env->interrupt_request &= ~CPU_INTERRUPT_SMI;
do_smm_enter();
#if defined(__sparc__) && !defined(HOST_SOLARIS)
@@ -420,10 +405,11 @@ int cpu_exec(CPUState *env1)
T0 = 0;
#endif
} else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
- (env->eflags & IF_MASK) &&
+ (env->eflags & IF_MASK || env->hflags & HF_HIF_MASK) &&
!(env->hflags & HF_INHIBIT_IRQ_MASK)) {
int intno;
- env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ svm_check_intercept(SVM_EXIT_INTR);
+ env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
intno = cpu_get_pic_interrupt(env);
if (loglevel & CPU_LOG_TB_IN_ASM) {
fprintf(logfile, "Servicing hardware INT=0x%02x\n", intno);
@@ -436,6 +422,25 @@ int cpu_exec(CPUState *env1)
#else
T0 = 0;
#endif
+#if !defined(CONFIG_USER_ONLY)
+ } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
+ (env->eflags & IF_MASK) && !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
+ int intno;
+ /* FIXME: this should respect TPR */
+ env->interrupt_request &= ~CPU_INTERRUPT_VIRQ;
+ svm_check_intercept(SVM_EXIT_VINTR);
+ intno = ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_vector));
+ if (loglevel & CPU_LOG_TB_IN_ASM)
+ fprintf(logfile, "Servicing virtual hardware INT=0x%02x\n", intno);
+ do_interrupt(intno, 0, 0, -1, 1);
+ stl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl),
+ ldl_phys(env->vm_vmcb + offsetof(struct vmcb, control.int_ctl)) & ~V_IRQ_MASK);
+#if defined(__sparc__) && !defined(HOST_SOLARIS)
+ tmp_T0 = 0;
+#else
+ T0 = 0;
+#endif
+#endif
}
#elif defined(TARGET_PPC)
#if 0
@@ -443,37 +448,22 @@ int cpu_exec(CPUState *env1)
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);
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
+ ppc_hw_interrupt(env);
+ if (env->pending_interrupts == 0)
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
#if defined(__sparc__) && !defined(HOST_SOLARIS)
- tmp_T0 = 0;
-#else
- T0 = 0;
-#endif
- } 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;
-#if defined(__sparc__) && !defined(HOST_SOLARIS)
- tmp_T0 = 0;
+ tmp_T0 = 0;
#else
- T0 = 0;
+ T0 = 0;
#endif
- }
}
#elif defined(TARGET_MIPS)
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
+ (env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
(env->CP0_Status & (1 << CP0St_IE)) &&
- (env->CP0_Status & env->CP0_Cause & 0x0000FF00) &&
- !(env->hflags & MIPS_HFLAG_EXL) &&
- !(env->hflags & MIPS_HFLAG_ERL) &&
+ !(env->CP0_Status & (1 << CP0St_EXL)) &&
+ !(env->CP0_Status & (1 << CP0St_ERL)) &&
!(env->hflags & MIPS_HFLAG_DM)) {
/* Raise it */
env->exception_index = EXCP_EXT_INTERRUPT;
@@ -497,6 +487,9 @@ int cpu_exec(CPUState *env1)
env->interrupt_request &= ~CPU_INTERRUPT_HARD;
do_interrupt(env->interrupt_index);
env->interrupt_index = 0;
+#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
+ cpu_check_irqs(env);
+#endif
#if defined(__sparc__) && !defined(HOST_SOLARIS)
tmp_T0 = 0;
#else
@@ -506,12 +499,7 @@ int cpu_exec(CPUState *env1)
} else if (interrupt_request & CPU_INTERRUPT_TIMER) {
//do_interrupt(0, 0, 0, 0, 0);
env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
- } else if (interrupt_request & CPU_INTERRUPT_HALT) {
- env->interrupt_request &= ~CPU_INTERRUPT_HALT;
- env->halted = 1;
- env->exception_index = EXCP_HLT;
- cpu_loop_exit();
- }
+ }
#elif defined(TARGET_ARM)
if (interrupt_request & CPU_INTERRUPT_FIQ
&& !(env->uncached_cpsr & CPSR_F)) {
@@ -525,6 +513,22 @@ int cpu_exec(CPUState *env1)
}
#elif defined(TARGET_SH4)
/* XXXXX */
+#elif defined(TARGET_ALPHA)
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
+ do_interrupt(env);
+ }
+#elif defined(TARGET_M68K)
+ if (interrupt_request & CPU_INTERRUPT_HARD
+ && ((env->sr & SR_I) >> SR_I_SHIFT)
+ < env->pending_level) {
+ /* Real hardware gets the interrupt vector via an
+ IACK cycle at this point. Current emulated
+ hardware doesn't rely on this, so we
+ provide/save the vector when the interrupt is
+ first signalled. */
+ env->exception_index = env->pending_vector;
+ do_interrupt(1);
+ }
#endif
/* Don't use the cached interupt_request value,
do_interrupt may have updated the EXITTB flag. */
@@ -546,32 +550,9 @@ int cpu_exec(CPUState *env1)
}
#ifdef DEBUG_EXEC
if ((loglevel & CPU_LOG_TB_CPU)) {
-#if defined(TARGET_I386)
/* restore flags in standard format */
-#ifdef reg_EAX
- env->regs[R_EAX] = EAX;
-#endif
-#ifdef reg_EBX
- env->regs[R_EBX] = EBX;
-#endif
-#ifdef reg_ECX
- env->regs[R_ECX] = ECX;
-#endif
-#ifdef reg_EDX
- env->regs[R_EDX] = EDX;
-#endif
-#ifdef reg_ESI
- env->regs[R_ESI] = ESI;
-#endif
-#ifdef reg_EDI
- env->regs[R_EDI] = EDI;
-#endif
-#ifdef reg_EBP
- env->regs[R_EBP] = EBP;
-#endif
-#ifdef reg_ESP
- env->regs[R_ESP] = ESP;
-#endif
+ regs_to_env();
+#if defined(TARGET_I386)
env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
@@ -593,8 +574,10 @@ int cpu_exec(CPUState *env1)
cpu_dump_state(env, logfile, fprintf, 0);
#elif defined(TARGET_SH4)
cpu_dump_state(env, logfile, fprintf, 0);
+#elif defined(TARGET_ALPHA)
+ cpu_dump_state(env, logfile, fprintf, 0);
#else
-#error unsupported target CPU
+#error unsupported target CPU
#endif
}
#endif
@@ -608,7 +591,7 @@ int cpu_exec(CPUState *env1)
#endif
#if defined(__sparc__) && !defined(HOST_SOLARIS)
T0 = tmp_T0;
-#endif
+#endif
/* see if we can patch the calling TB. When the TB
spans two pages, we cannot safely do a direct
jump. */
@@ -619,7 +602,7 @@ int cpu_exec(CPUState *env1)
#endif
tb->page_addr[1] == -1
#if defined(TARGET_I386) && defined(USE_CODE_COPY)
- && (tb->cflags & CF_CODE_COPY) ==
+ && (tb->cflags & CF_CODE_COPY) ==
(((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)
#endif
) {
@@ -627,7 +610,7 @@ int cpu_exec(CPUState *env1)
tb_add_jump((TranslationBlock *)(long)(T0 & ~3), T0 & 3, tb);
#if defined(USE_CODE_COPY)
/* propagates the FP use info */
- ((TranslationBlock *)(T0 & ~3))->cflags |=
+ ((TranslationBlock *)(T0 & ~3))->cflags |=
(tb->cflags & CF_FP_USED);
#endif
spin_unlock(&tb_lock);
@@ -641,8 +624,9 @@ int cpu_exec(CPUState *env1)
__asm__ __volatile__("call %0\n\t"
"mov %%o7,%%i0"
: /* no outputs */
- : "r" (gen_func)
+ : "r" (gen_func)
: "i0", "i1", "i2", "i3", "i4", "i5",
+ "o0", "o1", "o2", "o3", "o4", "o5",
"l0", "l1", "l2", "l3", "l4", "l5",
"l6", "l7");
#elif defined(__arm__)
@@ -755,7 +739,7 @@ int cpu_exec(CPUState *env1)
cpu_loop_exit();
}
#endif
- }
+ } /* for(;;) */
} else {
env_to_regs();
}
@@ -784,6 +768,7 @@ int cpu_exec(CPUState *env1)
| env->cc_dest | (env->cc_x << 4);
#elif defined(TARGET_MIPS)
#elif defined(TARGET_SH4)
+#elif defined(TARGET_ALPHA)
/* XXXXX */
#else
#error unsupported target CPU
@@ -796,7 +781,7 @@ int cpu_exec(CPUState *env1)
#include "hostregs_helper.h"
/* fail safe : never use cpu_single_env outside cpu_exec() */
- cpu_single_env = NULL;
+ cpu_single_env = NULL;
return ret;
}
@@ -823,7 +808,7 @@ void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
env = s;
if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK)) {
selector &= 0xffff;
- cpu_x86_load_seg_cache(env, seg_reg, selector,
+ cpu_x86_load_seg_cache(env, seg_reg, selector,
(selector << 4), 0xffff, 0);
} else {
load_seg(seg_reg, selector);
@@ -837,7 +822,7 @@ void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32)
saved_env = env;
env = s;
-
+
helper_fsave((target_ulong)ptr, data32);
env = saved_env;
@@ -849,7 +834,7 @@ void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
saved_env = env;
env = s;
-
+
helper_frstor((target_ulong)ptr, data32);
env = saved_env;
@@ -866,7 +851,7 @@ 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;
@@ -875,7 +860,7 @@ 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)
- qemu_printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
+ 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 */
@@ -884,7 +869,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
}
/* 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 */
@@ -899,7 +884,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
}
if (ret == 1) {
#if 0
- printf("PF exception: EIP=0x%08x CR2=0x%08x error=0x%x\n",
+ 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
@@ -926,7 +911,7 @@ 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",
+ 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 */
@@ -962,7 +947,7 @@ 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",
+ 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 */
@@ -994,11 +979,11 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
{
TranslationBlock *tb;
int ret;
-
+
if (cpu_single_env)
env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
- printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
+ 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 */
@@ -1022,7 +1007,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
}
if (ret == 1) {
#if 0
- printf("PF exception: NIP=0x%08x error=0x%x %p\n",
+ 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
@@ -1048,7 +1033,7 @@ 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",
+ 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 */
@@ -1083,11 +1068,11 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
{
TranslationBlock *tb;
int ret;
-
+
if (cpu_single_env)
env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
- printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
+ 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 */
@@ -1111,8 +1096,8 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
}
if (ret == 1) {
#if 0
- printf("PF exception: NIP=0x%08x error=0x%x %p\n",
- env->nip, env->error_code, tb);
+ printf("PF exception: PC=0x" TARGET_FMT_lx " error=0x%x %p\n",
+ env->PC, env->error_code, tb);
#endif
/* we restore the process signal mask as the sigreturn should
do it (XXX: use sigsetjmp) */
@@ -1133,11 +1118,11 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
{
TranslationBlock *tb;
int ret;
-
+
if (cpu_single_env)
env = cpu_single_env; /* XXX: find a correct solution for multithread */
#if defined(DEBUG_SIGNAL)
- printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
+ 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 */
@@ -1160,7 +1145,52 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
cpu_restore_state(tb, env, pc, puc);
}
#if 0
- printf("PF exception: NIP=0x%08x error=0x%x %p\n",
+ 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);
+ cpu_loop_exit();
+ /* never comes here */
+ return 1;
+}
+
+#elif defined (TARGET_ALPHA)
+static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
+ int is_write, sigset_t *old_set,
+ void *puc)
+{
+ TranslationBlock *tb;
+ int ret;
+
+ if (cpu_single_env)
+ env = cpu_single_env; /* XXX: find a correct solution for multithread */
+#if defined(DEBUG_SIGNAL)
+ printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n",
+ pc, address, is_write, *(unsigned long *)old_set);
+#endif
+ /* XXX: locking issue */
+ if (is_write && page_unprotect(h2g(address), pc, puc)) {
+ return 1;
+ }
+
+ /* see if it is an MMU fault */
+ ret = cpu_alpha_handle_mmu_fault(env, address, is_write, 1, 0);
+ if (ret < 0)
+ return 0; /* not an MMU fault */
+ if (ret == 0)
+ return 1; /* the MMU fault was handled without causing real CPU fault */
+
+ /* now we have a real cpu fault */
+ tb = tb_find_pc(pc);
+ if (tb) {
+ /* the PC is inside the translated code. It means that we have
+ a virtual CPU fault */
+ cpu_restore_state(tb, env, pc, puc);
+ }
+#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
@@ -1189,7 +1219,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
#endif
#if defined(USE_CODE_COPY)
-static void cpu_send_trap(unsigned long pc, int trap,
+static void cpu_send_trap(unsigned long pc, int trap,
struct ucontext *uc)
{
TranslationBlock *tb;
@@ -1208,7 +1238,7 @@ static void cpu_send_trap(unsigned long pc, int trap,
}
#endif
-int cpu_signal_handler(int host_signum, void *pinfo,
+int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
@@ -1231,8 +1261,8 @@ int cpu_signal_handler(int host_signum, void *pinfo,
return 1;
} else
#endif
- return handle_cpu_signal(pc, (unsigned long)info->si_addr,
- trapno == 0xe ?
+ return handle_cpu_signal(pc, (unsigned long)info->si_addr,
+ trapno == 0xe ?
(ERROR_sig(uc) >> 1) & 1 : 0,
&uc->uc_sigmask, puc);
}
@@ -1247,8 +1277,8 @@ int cpu_signal_handler(int host_signum, void *pinfo,
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 ?
+ 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);
}
@@ -1304,7 +1334,7 @@ typedef struct ucontext SIGCONTEXT;
# define TRAP_sig(context) EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
#endif /* __APPLE__ */
-int cpu_signal_handler(int host_signum, void *pinfo,
+int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
@@ -1322,13 +1352,13 @@ int cpu_signal_handler(int host_signum, void *pinfo,
if (TRAP_sig(uc) != 0x400 && (DSISR_sig(uc) & 0x02000000))
is_write = 1;
#endif
- return handle_cpu_signal(pc, (unsigned long)info->si_addr,
+ return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, &uc->uc_sigmask, puc);
}
#elif defined(__alpha__)
-int cpu_signal_handler(int host_signum, void *pinfo,
+int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
@@ -1353,12 +1383,12 @@ int cpu_signal_handler(int host_signum, void *pinfo,
is_write = 1;
}
- return handle_cpu_signal(pc, (unsigned long)info->si_addr,
+ return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, &uc->uc_sigmask, puc);
}
#elif defined(__sparc__)
-int cpu_signal_handler(int host_signum, void *pinfo,
+int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
@@ -1367,7 +1397,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
unsigned long pc;
int is_write;
uint32_t insn;
-
+
/* XXX: is there a standard glibc define ? */
pc = regs[1];
/* XXX: need kernel patch to get write flag faster */
@@ -1386,42 +1416,42 @@ int cpu_signal_handler(int host_signum, void *pinfo,
break;
}
}
- return handle_cpu_signal(pc, (unsigned long)info->si_addr,
+ return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, sigmask, NULL);
}
#elif defined(__arm__)
-int cpu_signal_handler(int host_signum, void *pinfo,
+int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
int is_write;
-
+
pc = uc->uc_mcontext.gregs[R15];
/* XXX: compute is_write */
is_write = 0;
- return handle_cpu_signal(pc, (unsigned long)info->si_addr,
+ return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write,
&uc->uc_sigmask, puc);
}
#elif defined(__mc68000)
-int cpu_signal_handler(int host_signum, void *pinfo,
+int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
int is_write;
-
+
pc = uc->uc_mcontext.gregs[16];
/* XXX: compute is_write */
is_write = 0;
- return handle_cpu_signal(pc, (unsigned long)info->si_addr,
+ return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write,
&uc->uc_sigmask, puc);
}
@@ -1462,20 +1492,35 @@ int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
#elif defined(__s390__)
-int cpu_signal_handler(int host_signum, void *pinfo,
+int cpu_signal_handler(int host_signum, void *pinfo,
void *puc)
{
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
int is_write;
-
+
pc = uc->uc_mcontext.psw.addr;
/* XXX: compute is_write */
is_write = 0;
- return handle_cpu_signal(pc, (unsigned long)info->si_addr,
- is_write,
- &uc->uc_sigmask, puc);
+ return handle_cpu_signal(pc, (unsigned long)info->si_addr,
+ is_write, &uc->uc_sigmask, puc);
+}
+
+#elif defined(__mips__)
+
+int cpu_signal_handler(int host_signum, void *pinfo,
+ void *puc)
+{
+ siginfo_t *info = pinfo;
+ struct ucontext *uc = puc;
+ greg_t pc = uc->uc_mcontext.pc;
+ int is_write;
+
+ /* XXX: compute is_write */
+ is_write = 0;
+ return handle_cpu_signal(pc, (unsigned long)info->si_addr,
+ is_write, &uc->uc_sigmask, puc);
}
#else
diff --git a/cutils.c b/cutils.c
index 352c47e21..074b5acd4 100644
--- a/cutils.c
+++ b/cutils.c
@@ -1,6 +1,6 @@
/*
* Simple C functions to supplement the C library
- *
+ *
* Copyright (c) 2006 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -45,7 +45,7 @@ char *pstrcat(char *buf, int buf_size, const char *s)
{
int len;
len = strlen(buf);
- if (len < buf_size)
+ if (len < buf_size)
pstrcpy(buf + len, buf_size - len, s);
return buf;
}
diff --git a/d3des.c b/d3des.c
new file mode 100644
index 000000000..eaca58165
--- /dev/null
+++ b/d3des.c
@@ -0,0 +1,434 @@
+/*
+ * This is D3DES (V5.09) by Richard Outerbridge with the double and
+ * triple-length support removed for use in VNC. Also the bytebit[] array
+ * has been reversed so that the most significant bit in each byte of the
+ * key is ignored, not the least significant.
+ *
+ * These changes are:
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This software 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.
+ */
+
+/* D3DES (V5.09) -
+ *
+ * A portable, public domain, version of the Data Encryption Standard.
+ *
+ * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
+ * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
+ * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
+ * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
+ * for humouring me on.
+ *
+ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
+ * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
+ */
+
+#include "d3des.h"
+
+static void scrunch(unsigned char *, unsigned long *);
+static void unscrun(unsigned long *, unsigned char *);
+static void desfunc(unsigned long *, unsigned long *);
+static void cookey(unsigned long *);
+
+static unsigned long KnL[32] = { 0L };
+
+static unsigned short bytebit[8] = {
+ 01, 02, 04, 010, 020, 040, 0100, 0200 };
+
+static unsigned long bigbyte[24] = {
+ 0x800000L, 0x400000L, 0x200000L, 0x100000L,
+ 0x80000L, 0x40000L, 0x20000L, 0x10000L,
+ 0x8000L, 0x4000L, 0x2000L, 0x1000L,
+ 0x800L, 0x400L, 0x200L, 0x100L,
+ 0x80L, 0x40L, 0x20L, 0x10L,
+ 0x8L, 0x4L, 0x2L, 0x1L };
+
+/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
+
+static unsigned char pc1[56] = {
+ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
+ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
+ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
+ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
+
+static unsigned char totrot[16] = {
+ 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
+
+static unsigned char pc2[48] = {
+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
+
+void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */
+unsigned char *key;
+int edf;
+{
+ register int i, j, l, m, n;
+ unsigned char pc1m[56], pcr[56];
+ unsigned long kn[32];
+
+ for ( j = 0; j < 56; j++ ) {
+ l = pc1[j];
+ m = l & 07;
+ pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
+ }
+ for( i = 0; i < 16; i++ ) {
+ if( edf == DE1 ) m = (15 - i) << 1;
+ else m = i << 1;
+ n = m + 1;
+ kn[m] = kn[n] = 0L;
+ for( j = 0; j < 28; j++ ) {
+ l = j + totrot[i];
+ if( l < 28 ) pcr[j] = pc1m[l];
+ else pcr[j] = pc1m[l - 28];
+ }
+ for( j = 28; j < 56; j++ ) {
+ l = j + totrot[i];
+ if( l < 56 ) pcr[j] = pc1m[l];
+ else pcr[j] = pc1m[l - 28];
+ }
+ for( j = 0; j < 24; j++ ) {
+ if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
+ if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
+ }
+ }
+ cookey(kn);
+ return;
+ }
+
+static void cookey(raw1)
+register unsigned long *raw1;
+{
+ register unsigned long *cook, *raw0;
+ unsigned long dough[32];
+ register int i;
+
+ cook = dough;
+ for( i = 0; i < 16; i++, raw1++ ) {
+ raw0 = raw1++;
+ *cook = (*raw0 & 0x00fc0000L) << 6;
+ *cook |= (*raw0 & 0x00000fc0L) << 10;
+ *cook |= (*raw1 & 0x00fc0000L) >> 10;
+ *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
+ *cook = (*raw0 & 0x0003f000L) << 12;
+ *cook |= (*raw0 & 0x0000003fL) << 16;
+ *cook |= (*raw1 & 0x0003f000L) >> 4;
+ *cook++ |= (*raw1 & 0x0000003fL);
+ }
+ usekey(dough);
+ return;
+ }
+
+void cpkey(into)
+register unsigned long *into;
+{
+ register unsigned long *from, *endp;
+
+ from = KnL, endp = &KnL[32];
+ while( from < endp ) *into++ = *from++;
+ return;
+ }
+
+void usekey(from)
+register unsigned long *from;
+{
+ register unsigned long *to, *endp;
+
+ to = KnL, endp = &KnL[32];
+ while( to < endp ) *to++ = *from++;
+ return;
+ }
+
+void des(inblock, outblock)
+unsigned char *inblock, *outblock;
+{
+ unsigned long work[2];
+
+ scrunch(inblock, work);
+ desfunc(work, KnL);
+ unscrun(work, outblock);
+ return;
+ }
+
+static void scrunch(outof, into)
+register unsigned char *outof;
+register unsigned long *into;
+{
+ *into = (*outof++ & 0xffL) << 24;
+ *into |= (*outof++ & 0xffL) << 16;
+ *into |= (*outof++ & 0xffL) << 8;
+ *into++ |= (*outof++ & 0xffL);
+ *into = (*outof++ & 0xffL) << 24;
+ *into |= (*outof++ & 0xffL) << 16;
+ *into |= (*outof++ & 0xffL) << 8;
+ *into |= (*outof & 0xffL);
+ return;
+ }
+
+static void unscrun(outof, into)
+register unsigned long *outof;
+register unsigned char *into;
+{
+ *into++ = (unsigned char)((*outof >> 24) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 16) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 8) & 0xffL);
+ *into++ = (unsigned char)(*outof++ & 0xffL);
+ *into++ = (unsigned char)((*outof >> 24) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 16) & 0xffL);
+ *into++ = (unsigned char)((*outof >> 8) & 0xffL);
+ *into = (unsigned char)(*outof & 0xffL);
+ return;
+ }
+
+static unsigned long SP1[64] = {
+ 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
+ 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
+ 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
+ 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
+ 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
+ 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
+ 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
+ 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
+ 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
+ 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
+ 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
+ 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
+ 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
+ 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
+ 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
+
+static unsigned long SP2[64] = {
+ 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
+ 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
+ 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
+ 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
+ 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
+ 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
+ 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
+ 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
+ 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
+ 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
+ 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
+ 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
+ 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
+ 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
+ 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
+ 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
+
+static unsigned long SP3[64] = {
+ 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
+ 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
+ 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
+ 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
+ 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
+ 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
+ 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
+ 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
+ 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
+ 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
+ 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
+ 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
+ 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
+ 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
+ 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
+ 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
+
+static unsigned long SP4[64] = {
+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
+ 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
+ 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
+ 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
+ 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
+ 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
+ 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
+ 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
+ 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
+ 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
+ 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
+ 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
+ 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
+ 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
+ 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
+ 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
+
+static unsigned long SP5[64] = {
+ 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
+ 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
+ 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
+ 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
+ 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
+ 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
+ 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
+ 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
+ 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
+ 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
+ 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
+ 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
+ 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
+ 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
+ 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
+ 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
+
+static unsigned long SP6[64] = {
+ 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
+ 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
+ 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
+ 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
+ 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
+ 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
+ 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
+ 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
+ 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
+ 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
+ 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
+ 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
+ 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
+ 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
+ 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
+ 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
+
+static unsigned long SP7[64] = {
+ 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
+ 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
+ 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
+ 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
+ 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
+ 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
+ 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
+ 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
+ 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
+ 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
+ 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
+ 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
+ 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
+ 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
+ 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
+ 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
+
+static unsigned long SP8[64] = {
+ 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
+ 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
+ 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
+ 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
+ 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
+ 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
+ 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
+ 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
+ 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
+ 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
+ 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
+ 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
+ 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
+ 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
+ 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
+ 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
+
+static void desfunc(block, keys)
+register unsigned long *block, *keys;
+{
+ register unsigned long fval, work, right, leftt;
+ register int round;
+
+ leftt = block[0];
+ right = block[1];
+ work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
+ right ^= work;
+ leftt ^= (work << 4);
+ work = ((leftt >> 16) ^ right) & 0x0000ffffL;
+ right ^= work;
+ leftt ^= (work << 16);
+ work = ((right >> 2) ^ leftt) & 0x33333333L;
+ leftt ^= work;
+ right ^= (work << 2);
+ work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
+ leftt ^= work;
+ right ^= (work << 8);
+ right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
+ work = (leftt ^ right) & 0xaaaaaaaaL;
+ leftt ^= work;
+ right ^= work;
+ leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
+
+ for( round = 0; round < 8; round++ ) {
+ work = (right << 28) | (right >> 4);
+ work ^= *keys++;
+ fval = SP7[ work & 0x3fL];
+ fval |= SP5[(work >> 8) & 0x3fL];
+ fval |= SP3[(work >> 16) & 0x3fL];
+ fval |= SP1[(work >> 24) & 0x3fL];
+ work = right ^ *keys++;
+ fval |= SP8[ work & 0x3fL];
+ fval |= SP6[(work >> 8) & 0x3fL];
+ fval |= SP4[(work >> 16) & 0x3fL];
+ fval |= SP2[(work >> 24) & 0x3fL];
+ leftt ^= fval;
+ work = (leftt << 28) | (leftt >> 4);
+ work ^= *keys++;
+ fval = SP7[ work & 0x3fL];
+ fval |= SP5[(work >> 8) & 0x3fL];
+ fval |= SP3[(work >> 16) & 0x3fL];
+ fval |= SP1[(work >> 24) & 0x3fL];
+ work = leftt ^ *keys++;
+ fval |= SP8[ work & 0x3fL];
+ fval |= SP6[(work >> 8) & 0x3fL];
+ fval |= SP4[(work >> 16) & 0x3fL];
+ fval |= SP2[(work >> 24) & 0x3fL];
+ right ^= fval;
+ }
+
+ right = (right << 31) | (right >> 1);
+ work = (leftt ^ right) & 0xaaaaaaaaL;
+ leftt ^= work;
+ right ^= work;
+ leftt = (leftt << 31) | (leftt >> 1);
+ work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
+ right ^= work;
+ leftt ^= (work << 8);
+ work = ((leftt >> 2) ^ right) & 0x33333333L;
+ right ^= work;
+ leftt ^= (work << 2);
+ work = ((right >> 16) ^ leftt) & 0x0000ffffL;
+ leftt ^= work;
+ right ^= (work << 16);
+ work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
+ leftt ^= work;
+ right ^= (work << 4);
+ *block++ = right;
+ *block = leftt;
+ return;
+ }
+
+/* Validation sets:
+ *
+ * Single-length key, single-length plaintext -
+ * Key : 0123 4567 89ab cdef
+ * Plain : 0123 4567 89ab cde7
+ * Cipher : c957 4425 6a5e d31d
+ *
+ * Double-length key, single-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210
+ * Plain : 0123 4567 89ab cde7
+ * Cipher : 7f1d 0a77 826b 8aff
+ *
+ * Double-length key, double-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210
+ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
+ * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
+ *
+ * Triple-length key, single-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
+ * Plain : 0123 4567 89ab cde7
+ * Cipher : de0b 7c06 ae5e 0ed5
+ *
+ * Triple-length key, double-length plaintext -
+ * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
+ * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
+ * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
+ *
+ * d3des V5.0a rwo 9208.07 18:44 Graven Imagery
+ **********************************************************************/
diff --git a/d3des.h b/d3des.h
new file mode 100644
index 000000000..ea3da44ce
--- /dev/null
+++ b/d3des.h
@@ -0,0 +1,51 @@
+/*
+ * This is D3DES (V5.09) by Richard Outerbridge with the double and
+ * triple-length support removed for use in VNC.
+ *
+ * These changes are:
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * This software 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.
+ */
+
+/* d3des.h -
+ *
+ * Headers and defines for d3des.c
+ * Graven Imagery, 1992.
+ *
+ * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge
+ * (GEnie : OUTER; CIS : [71755,204])
+ */
+
+#define EN0 0 /* MODE == encrypt */
+#define DE1 1 /* MODE == decrypt */
+
+extern void deskey(unsigned char *, int);
+/* hexkey[8] MODE
+ * Sets the internal key register according to the hexadecimal
+ * key contained in the 8 bytes of hexkey, according to the DES,
+ * for encryption or decryption according to MODE.
+ */
+
+extern void usekey(unsigned long *);
+/* cookedkey[32]
+ * Loads the internal key register with the data in cookedkey.
+ */
+
+extern void cpkey(unsigned long *);
+/* cookedkey[32]
+ * Copies the contents of the internal key register into the storage
+ * located at &cookedkey[0].
+ */
+
+extern void des(unsigned char *, unsigned char *);
+/* from[8] to[8]
+ * Encrypts/Decrypts (according to the key currently loaded in the
+ * internal key register) one block of eight bytes at address 'from'
+ * into the block at address 'to'. They can be the same.
+ */
+
+/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery
+ ********************************************************************/
diff --git a/darwin-user/main.c b/darwin-user/main.c
index 78cf864c1..d0de491e0 100644
--- a/darwin-user/main.c
+++ b/darwin-user/main.c
@@ -124,32 +124,47 @@ 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)
+uint32_t cpu_ppc_load_atbl (CPUState *env)
{
- /* TO FIX */
+ return cpu_ppc_get_tb(env) & 0xFFFFFFFF;
}
-void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
+uint32_t cpu_ppc_load_atbu (CPUState *env)
{
- cpu_ppc_store_tb(env, ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
+ return cpu_ppc_get_tb(env) >> 32;
}
-void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
+uint32_t cpu_ppc601_load_rtcu (CPUState *env)
{
- cpu_ppc_store_tb(env, ((uint64_t)cpu_ppc_load_tbl(env) << 32) | value);
+ cpu_ppc_load_tbu(env);
}
-uint32_t cpu_ppc_load_decr (CPUState *env)
+uint32_t cpu_ppc601_load_rtcl (CPUState *env)
+{
+ return cpu_ppc_load_tbl(env) & 0x3FFFFF80;
+}
+
+/* XXX: to be fixed */
+int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, target_ulong *valp)
{
- /* TO FIX */
return -1;
}
-void cpu_ppc_store_decr (CPUState *env, uint32_t value)
+int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, target_ulong val)
{
- /* TO FIX */
+ return -1;
}
+#define EXCP_DUMP(env, fmt, args...) \
+do { \
+ fprintf(stderr, fmt , ##args); \
+ cpu_dump_state(env, stderr, fprintf, 0); \
+ if (loglevel != 0) { \
+ fprintf(logfile, fmt , ##args); \
+ cpu_dump_state(env, logfile, fprintf, 0); \
+ } \
+} while (0)
+
void cpu_loop(CPUPPCState *env)
{
int trapnr;
@@ -158,271 +173,368 @@ void cpu_loop(CPUPPCState *env)
for(;;) {
trapnr = cpu_ppc_exec(env);
- if (trapnr != EXCP_SYSCALL_USER && trapnr != EXCP_BRANCH &&
- trapnr != EXCP_TRACE) {
- if (loglevel > 0) {
- cpu_dump_state(env, logfile, fprintf, 0);
- }
- }
switch(trapnr) {
- case EXCP_NONE:
+ case POWERPC_EXCP_NONE:
+ /* Just go on */
break;
- case EXCP_SYSCALL_USER:
- /* system call */
- if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
- ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
- env->gpr[5], env->gpr[6], env->gpr[7],
- env->gpr[8], env->gpr[9], env->gpr[10]*/);
- else if(((int)env->gpr[0])<0)
- ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
- env->gpr[5], env->gpr[6], env->gpr[7],
- env->gpr[8], env->gpr[9], env->gpr[10]);
- else
- ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
- env->gpr[5], env->gpr[6], env->gpr[7],
- env->gpr[8], env->gpr[9], env->gpr[10]);
-
- /* Unix syscall error signaling */
- if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
- {
- if( (int)ret < 0 )
- env->nip += 0;
- else
- env->nip += 4;
- }
-
- /* Return value */
- env->gpr[3] = ret;
+ case POWERPC_EXCP_CRITICAL: /* Critical input */
+ cpu_abort(env, "Critical interrupt while in user mode. "
+ "Aborting\n");
break;
- case EXCP_RESET:
- /* Should not happen ! */
- fprintf(stderr, "RESET asked... Stop emulation\n");
- if (loglevel)
- fprintf(logfile, "RESET asked... Stop emulation\n");
- abort();
- case EXCP_MACHINE_CHECK:
- fprintf(stderr, "Machine check exeption... Stop emulation\n");
- if (loglevel)
- fprintf(logfile, "RESET asked... Stop emulation\n");
- info.si_signo = SIGBUS;
- info.si_errno = 0;
- info.si_code = BUS_OBJERR;
- info.si_addr = (void*)(env->nip - 4);
- queue_signal(info.si_signo, &info);
- case EXCP_DSI:
+ case POWERPC_EXCP_MCHECK: /* Machine check exception */
+ cpu_abort(env, "Machine check exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DSI: /* Data storage exception */
#ifndef DAR
/* To deal with multiple qemu header version as host for the darwin-user code */
# define DAR SPR_DAR
#endif
- fprintf(stderr, "Invalid data memory access: 0x%08x\n", env->spr[DAR]);
- if (loglevel) {
- fprintf(logfile, "Invalid data memory access: 0x%08x\n",
- env->spr[DAR]);
- }
+ EXCP_DUMP(env, "Invalid data memory access: 0x" ADDRX "\n",
+ env->spr[SPR_DAR]);
/* Handle this via the gdb */
gdb_handlesig (env, SIGSEGV);
info.si_addr = (void*)env->nip;
queue_signal(info.si_signo, &info);
break;
- case EXCP_ISI:
- fprintf(stderr, "Invalid instruction fetch\n");
- if (loglevel)
- fprintf(logfile, "Invalid instruction fetch\n");
+ case POWERPC_EXCP_ISI: /* Instruction storage exception */
+ EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" ADDRX "\n",
+ env->spr[SPR_DAR]);
/* Handle this via the gdb */
gdb_handlesig (env, SIGSEGV);
info.si_addr = (void*)(env->nip - 4);
queue_signal(info.si_signo, &info);
break;
- case EXCP_EXTERNAL:
- /* Should not happen ! */
- fprintf(stderr, "External interruption... Stop emulation\n");
- if (loglevel)
- fprintf(logfile, "External interruption... Stop emulation\n");
- abort();
- case EXCP_ALIGN:
- fprintf(stderr, "Invalid unaligned memory access\n");
- if (loglevel)
- fprintf(logfile, "Invalid unaligned memory access\n");
- info.si_signo = SIGBUS;
+ case POWERPC_EXCP_EXTERNAL: /* External input */
+ cpu_abort(env, "External interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ALIGN: /* Alignment exception */
+ EXCP_DUMP(env, "Unaligned memory access\n");
info.si_errno = 0;
info.si_code = BUS_ADRALN;
info.si_addr = (void*)(env->nip - 4);
queue_signal(info.si_signo, &info);
break;
- case EXCP_PROGRAM:
+ case POWERPC_EXCP_PROGRAM: /* Program exception */
+ /* XXX: check this */
switch (env->error_code & ~0xF) {
- case EXCP_FP:
- fprintf(stderr, "Program exception\n");
- if (loglevel)
- fprintf(logfile, "Program exception\n");
- /* Set FX */
- env->fpscr[7] |= 0x8;
- /* Finally, update FEX */
- if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
- ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
- env->fpscr[7] |= 0x4;
- info.si_signo = SIGFPE;
- info.si_errno = 0;
- switch (env->error_code & 0xF) {
- case EXCP_FP_OX:
- info.si_code = FPE_FLTOVF;
- break;
- case EXCP_FP_UX:
- info.si_code = FPE_FLTUND;
- break;
- case EXCP_FP_ZX:
- case EXCP_FP_VXZDZ:
- info.si_code = FPE_FLTDIV;
- break;
- case EXCP_FP_XX:
- info.si_code = FPE_FLTRES;
- break;
- case EXCP_FP_VXSOFT:
- info.si_code = FPE_FLTINV;
- break;
- case EXCP_FP_VXNAN:
- case EXCP_FP_VXISI:
- case EXCP_FP_VXIDI:
- case EXCP_FP_VXIMZ:
- case EXCP_FP_VXVC:
- case EXCP_FP_VXSQRT:
- case EXCP_FP_VXCVI:
- info.si_code = FPE_FLTSUB;
- break;
- default:
- fprintf(stderr, "Unknown floating point exception "
- "(%02x)\n", env->error_code);
- if (loglevel) {
- fprintf(logfile, "Unknown floating point exception "
- "(%02x)\n", env->error_code & 0xF);
- }
- }
- break;
- case EXCP_INVAL:
- fprintf(stderr, "Invalid instruction\n");
- if (loglevel)
- fprintf(logfile, "Invalid instruction\n");
- info.si_signo = SIGILL;
- info.si_errno = 0;
- switch (env->error_code & 0xF) {
- case EXCP_INVAL_INVAL:
- info.si_code = ILL_ILLOPC;
- break;
- case EXCP_INVAL_LSWX:
- info.si_code = ILL_ILLOPN;
- break;
- case EXCP_INVAL_SPR:
- info.si_code = ILL_PRVREG;
- break;
- case EXCP_INVAL_FP:
- info.si_code = ILL_COPROC;
- break;
- default:
- fprintf(stderr, "Unknown invalid operation (%02x)\n",
- env->error_code & 0xF);
- if (loglevel) {
- fprintf(logfile, "Unknown invalid operation (%02x)\n",
- env->error_code & 0xF);
- }
- info.si_code = ILL_ILLADR;
- break;
- }
- /* Handle this via the gdb */
- gdb_handlesig (env, SIGSEGV);
+ case POWERPC_EXCP_FP:
+ EXCP_DUMP(env, "Floating point program exception\n");
+ /* Set FX */
+ env->fpscr[7] |= 0x8;
+ /* Finally, update FEX */
+ if ((((env->fpscr[7] & 0x3) << 3) | (env->fpscr[6] >> 1)) &
+ ((env->fpscr[1] << 1) | (env->fpscr[0] >> 3)))
+ env->fpscr[7] |= 0x4;
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ switch (env->error_code & 0xF) {
+ case POWERPC_EXCP_FP_OX:
+ info.si_code = FPE_FLTOVF;
+ break;
+ case POWERPC_EXCP_FP_UX:
+ info.si_code = FPE_FLTUND;
+ break;
+ case POWERPC_EXCP_FP_ZX:
+ case POWERPC_EXCP_FP_VXZDZ:
+ info.si_code = FPE_FLTDIV;
+ break;
+ case POWERPC_EXCP_FP_XX:
+ info.si_code = FPE_FLTRES;
+ break;
+ case POWERPC_EXCP_FP_VXSOFT:
+ info.si_code = FPE_FLTINV;
+ break;
+ case POWERPC_EXCP_FP_VXNAN:
+ case POWERPC_EXCP_FP_VXISI:
+ case POWERPC_EXCP_FP_VXIDI:
+ case POWERPC_EXCP_FP_VXIMZ:
+ case POWERPC_EXCP_FP_VXVC:
+ case POWERPC_EXCP_FP_VXSQRT:
+ case POWERPC_EXCP_FP_VXCVI:
+ info.si_code = FPE_FLTSUB;
+ break;
+ default:
+ EXCP_DUMP(env, "Unknown floating point exception (%02x)\n",
+ env->error_code);
+ break;
+ }
+ break;
+ case POWERPC_EXCP_INVAL:
+ EXCP_DUMP(env, "Invalid instruction\n");
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ switch (env->error_code & 0xF) {
+ case POWERPC_EXCP_INVAL_INVAL:
+ info.si_code = ILL_ILLOPC;
+ break;
+ case POWERPC_EXCP_INVAL_LSWX:
+ info.si_code = ILL_ILLOPN;
+ break;
+ case POWERPC_EXCP_INVAL_SPR:
+ info.si_code = ILL_PRVREG;
+ break;
+ case POWERPC_EXCP_INVAL_FP:
+ info.si_code = ILL_COPROC;
break;
- case EXCP_PRIV:
- fprintf(stderr, "Privilege violation\n");
- if (loglevel)
- fprintf(logfile, "Privilege violation\n");
- info.si_signo = SIGILL;
- info.si_errno = 0;
- switch (env->error_code & 0xF) {
- case EXCP_PRIV_OPC:
- info.si_code = ILL_PRVOPC;
- break;
- case EXCP_PRIV_REG:
- info.si_code = ILL_PRVREG;
- break;
- default:
- fprintf(stderr, "Unknown privilege violation (%02x)\n",
- env->error_code & 0xF);
- info.si_code = ILL_PRVOPC;
- break;
- }
- break;
- case EXCP_TRAP:
- fprintf(stderr, "Tried to call a TRAP\n");
- if (loglevel)
- fprintf(logfile, "Tried to call a TRAP\n");
- abort();
default:
- /* Should not happen ! */
- fprintf(stderr, "Unknown program exception (%02x)\n",
- env->error_code);
- if (loglevel) {
- fprintf(logfile, "Unknwon program exception (%02x)\n",
- env->error_code);
- }
- abort();
+ EXCP_DUMP(env, "Unknown invalid operation (%02x)\n",
+ env->error_code & 0xF);
+ info.si_code = ILL_ILLADR;
+ break;
+ }
+ /* Handle this via the gdb */
+ gdb_handlesig (env, SIGSEGV);
+ break;
+ case POWERPC_EXCP_PRIV:
+ EXCP_DUMP(env, "Privilege violation\n");
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ switch (env->error_code & 0xF) {
+ case POWERPC_EXCP_PRIV_OPC:
+ info.si_code = ILL_PRVOPC;
+ break;
+ case POWERPC_EXCP_PRIV_REG:
+ info.si_code = ILL_PRVREG;
+ break;
+ default:
+ EXCP_DUMP(env, "Unknown privilege violation (%02x)\n",
+ env->error_code & 0xF);
+ info.si_code = ILL_PRVOPC;
+ break;
+ }
+ break;
+ case POWERPC_EXCP_TRAP:
+ cpu_abort(env, "Tried to call a TRAP\n");
+ break;
+ default:
+ /* Should not happen ! */
+ cpu_abort(env, "Unknown program exception (%02x)\n",
+ env->error_code);
+ break;
}
info.si_addr = (void*)(env->nip - 4);
queue_signal(info.si_signo, &info);
break;
- case EXCP_NO_FP:
- fprintf(stderr, "No floating point allowed\n");
- if (loglevel)
- fprintf(logfile, "No floating point allowed\n");
- info.si_signo = SIGILL;
+ case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
+ EXCP_DUMP(env, "No floating point allowed\n");
+ info.si_signo = SIGILL;
info.si_errno = 0;
info.si_code = ILL_COPROC;
info.si_addr = (void*)(env->nip - 4);
queue_signal(info.si_signo, &info);
break;
- case EXCP_DECR:
- /* Should not happen ! */
- fprintf(stderr, "Decrementer exception\n");
- if (loglevel)
- fprintf(logfile, "Decrementer exception\n");
- abort();
- case EXCP_TRACE:
- /* Pass to gdb: we use this to trace execution */
- gdb_handlesig (env, SIGTRAP);
+ case POWERPC_EXCP_SYSCALL: /* System call exception */
+ cpu_abort(env, "Syscall exception while in user mode. "
+ "Aborting\n");
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();
- }
+ case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
+ EXCP_DUMP(env, "No APU instruction allowed\n");
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_COPROC;
+ info.si_addr = (void*)(env->nip - 4);
+ queue_signal(info.si_signo, &info);
break;
- case EXCP_BRANCH:
- /* We stopped because of a jump... */
+ case POWERPC_EXCP_DECR: /* Decrementer exception */
+ cpu_abort(env, "Decrementer interrupt while in user mode. "
+ "Aborting\n");
break;
- case EXCP_INTERRUPT:
- /* Don't know why this should ever happen... */
- fprintf(stderr, "EXCP_INTERRUPT\n");
+ case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
+ cpu_abort(env, "Fix interval timer interrupt while in user mode. "
+ "Aborting\n");
break;
- case EXCP_DEBUG:
+ case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
+ cpu_abort(env, "Watchdog timer interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DTLB: /* Data TLB error */
+ cpu_abort(env, "Data TLB exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ITLB: /* Instruction TLB error */
+ cpu_abort(env, "Instruction TLB exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DEBUG: /* Debug interrupt */
gdb_handlesig (env, SIGTRAP);
break;
- default:
- fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n",
- trapnr);
- if (loglevel) {
- fprintf(logfile, "qemu: unhandled CPU exception 0x%02x - "
- "0x%02x - aborting\n", trapnr, env->error_code);
+#if defined(TARGET_PPCEMB)
+ case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavail. */
+ EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n");
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_COPROC;
+ info.si_addr = (void*)(env->nip - 4);
+ queue_signal(info.si_signo, &info);
+ break;
+ case POWERPC_EXCP_EFPDI: /* Embedded floating-point data IRQ */
+ cpu_abort(env, "Embedded floating-point data IRQ not handled\n");
+ break;
+ case POWERPC_EXCP_EFPRI: /* Embedded floating-point round IRQ */
+ cpu_abort(env, "Embedded floating-point round IRQ not handled\n");
+ break;
+ case POWERPC_EXCP_EPERFM: /* Embedded performance monitor IRQ */
+ cpu_abort(env, "Performance monitor exception not handled\n");
+ break;
+ case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
+ cpu_abort(env, "Doorbell interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
+ cpu_abort(env, "Doorbell critical interrupt while in user mode. "
+ "Aborting\n");
+ break;
+#endif /* defined(TARGET_PPCEMB) */
+ case POWERPC_EXCP_RESET: /* System reset exception */
+ cpu_abort(env, "Reset interrupt while in user mode. "
+ "Aborting\n");
+ break;
+#if defined(TARGET_PPC64) /* PowerPC 64 */
+ case POWERPC_EXCP_DSEG: /* Data segment exception */
+ cpu_abort(env, "Data segment exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_ISEG: /* Instruction segment exception */
+ cpu_abort(env, "Instruction segment exception "
+ "while in user mode. Aborting\n");
+ break;
+#endif /* defined(TARGET_PPC64) */
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+ case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
+ cpu_abort(env, "Hypervisor decrementer interrupt "
+ "while in user mode. Aborting\n");
+ break;
+#endif /* defined(TARGET_PPC64H) */
+ case POWERPC_EXCP_TRACE: /* Trace exception */
+ /* Nothing to do:
+ * we use this exception to emulate step-by-step execution mode.
+ */
+ break;
+#if defined(TARGET_PPC64H) /* PowerPC 64 with hypervisor mode support */
+ case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
+ cpu_abort(env, "Hypervisor data storage exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HISI: /* Hypervisor instruction storage excp */
+ cpu_abort(env, "Hypervisor instruction storage exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
+ cpu_abort(env, "Hypervisor data segment exception "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment excp */
+ cpu_abort(env, "Hypervisor instruction segment exception "
+ "while in user mode. Aborting\n");
+ break;
+#endif /* defined(TARGET_PPC64H) */
+ case POWERPC_EXCP_VPU: /* Vector unavailable exception */
+ EXCP_DUMP(env, "No Altivec instructions allowed\n");
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_COPROC;
+ info.si_addr = (void*)(env->nip - 4);
+ queue_signal(info.si_signo, &info);
+ break;
+ case POWERPC_EXCP_PIT: /* Programmable interval timer IRQ */
+ cpu_abort(env, "Programable interval timer interrupt "
+ "while in user mode. Aborting\n");
+ break;
+ case POWERPC_EXCP_IO: /* IO error exception */
+ cpu_abort(env, "IO error exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_RUNM: /* Run mode exception */
+ cpu_abort(env, "Run mode exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_EMUL: /* Emulation trap exception */
+ cpu_abort(env, "Emulation trap exception not handled\n");
+ break;
+ case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
+ cpu_abort(env, "Instruction fetch TLB exception "
+ "while in user-mode. Aborting");
+ break;
+ case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
+ cpu_abort(env, "Data load TLB exception while in user-mode. "
+ "Aborting");
+ break;
+ case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
+ cpu_abort(env, "Data store TLB exception while in user-mode. "
+ "Aborting");
+ break;
+ case POWERPC_EXCP_FPA: /* Floating-point assist exception */
+ cpu_abort(env, "Floating-point assist exception not handled\n");
+ break;
+ case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
+ cpu_abort(env, "Instruction address breakpoint exception "
+ "not handled\n");
+ break;
+ case POWERPC_EXCP_SMI: /* System management interrupt */
+ cpu_abort(env, "System management interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_THERM: /* Thermal interrupt */
+ cpu_abort(env, "Thermal interrupt interrupt while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_PERFM: /* Embedded performance monitor IRQ */
+ cpu_abort(env, "Performance monitor exception not handled\n");
+ break;
+ case POWERPC_EXCP_VPUA: /* Vector assist exception */
+ cpu_abort(env, "Vector assist exception not handled\n");
+ break;
+ case POWERPC_EXCP_SOFTP: /* Soft patch exception */
+ cpu_abort(env, "Soft patch exception not handled\n");
+ break;
+ case POWERPC_EXCP_MAINT: /* Maintenance exception */
+ cpu_abort(env, "Maintenance exception while in user mode. "
+ "Aborting\n");
+ break;
+ case POWERPC_EXCP_STOP: /* stop translation */
+ /* We did invalidate the instruction cache. Go on */
+ break;
+ case POWERPC_EXCP_BRANCH: /* branch instruction: */
+ /* We just stopped because of a branch. Go on */
+ break;
+ case POWERPC_EXCP_SYSCALL_USER:
+ /* system call in user-mode emulation */
+ /* system call */
+ if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
+ ret = do_unix_syscall(env, env->gpr[0]/*, env->gpr[3], env->gpr[4],
+ env->gpr[5], env->gpr[6], env->gpr[7],
+ env->gpr[8], env->gpr[9], env->gpr[10]*/);
+ else if(((int)env->gpr[0])<0)
+ ret = do_mach_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+ env->gpr[5], env->gpr[6], env->gpr[7],
+ env->gpr[8], env->gpr[9], env->gpr[10]);
+ else
+ ret = do_thread_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+ env->gpr[5], env->gpr[6], env->gpr[7],
+ env->gpr[8], env->gpr[9], env->gpr[10]);
+
+ /* Unix syscall error signaling */
+ if(((int)env->gpr[0]) <= SYS_MAXSYSCALL && ((int)env->gpr[0])>0)
+ {
+ if( (int)ret < 0 )
+ env->nip += 0;
+ else
+ env->nip += 4;
}
- abort();
+
+ /* Return value */
+ env->gpr[3] = ret;
+ break;
+ case EXCP_INTERRUPT:
+ /* just indicate that signals should be handled asap */
+ break;
+ default:
+ cpu_abort(env, "Unknown exception 0x%d. Aborting\n", trapnr);
+ break;
}
process_pending_signals(env);
}
diff --git a/darwin-user/mmap.c b/darwin-user/mmap.c
index ada613d36..b4055abe1 100644
--- a/darwin-user/mmap.c
+++ b/darwin-user/mmap.c
@@ -199,7 +199,7 @@ long target_mmap(unsigned long start, unsigned long len, int prot,
if (!(flags & MAP_FIXED)) {
#if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__)
- /* tell the kenel to search at the same place as i386 */
+ /* tell the kernel to search at the same place as i386 */
if (host_start == 0) {
host_start = last_start;
last_start += HOST_PAGE_ALIGN(len);
diff --git a/darwin-user/syscall.c b/darwin-user/syscall.c
index f2543aa44..f17e59101 100644
--- a/darwin-user/syscall.c
+++ b/darwin-user/syscall.c
@@ -53,6 +53,8 @@
#include <mach/ndr.h>
#include <mach/mig_errors.h>
+#include <sys/xattr.h>
+
#include "qemu.h"
//#define DEBUG_SYSCALL
@@ -367,7 +369,14 @@ static inline uint32_t target_mach_msg_trap(
case 200: /* host_info */
{
mig_reply_error_t *err = (mig_reply_error_t *)hdr;
- struct host_basic_info *data = (void *)(err+1);
+ struct {
+ uint32_t unknow1;
+ uint32_t max_cpus;
+ uint32_t avail_cpus;
+ uint32_t memory_size;
+ uint32_t cpu_type;
+ uint32_t cpu_subtype;
+ } *data = (void *)(err+1);
DPRINTF("maxcpu = 0x%x\n", data->max_cpus);
DPRINTF("numcpu = 0x%x\n", data->avail_cpus);
@@ -444,21 +453,49 @@ long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint3
case -31:
DPRINTF("mach_msg_trap(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
arg1, arg2, arg3, arg4, arg5, arg6, arg7);
-
ret = target_mach_msg_trap((mach_msg_header_t *)arg1, arg2, arg3, arg4, arg5, arg6, arg7);
-
break;
+/* may need more translation if target arch is different from host */
+#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
+ case -33:
+ DPRINTF("semaphore_signal_trap(0x%x)\n", arg1);
+ ret = semaphore_signal_trap(arg1);
+ break;
+ case -34:
+ DPRINTF("semaphore_signal_all_trap(0x%x)\n", arg1);
+ ret = semaphore_signal_all_trap(arg1);
+ break;
+ case -35:
+ DPRINTF("semaphore_signal_thread_trap(0x%x)\n", arg1, arg2);
+ ret = semaphore_signal_thread_trap(arg1,arg2);
+ break;
+#endif
case -36:
DPRINTF("semaphore_wait_trap(0x%x)\n", arg1);
extern int semaphore_wait_trap(int); // XXX: is there any header for that?
ret = semaphore_wait_trap(arg1);
break;
+/* may need more translation if target arch is different from host */
+#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
+ case -37:
+ DPRINTF("semaphore_wait_signal_trap(0x%x, 0x%x)\n", arg1, arg2);
+ ret = semaphore_wait_signal_trap(arg1,arg2);
+ break;
+#endif
case -43:
DPRINTF("map_fd(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
arg1, arg2, arg3, arg4, arg5);
ret = map_fd(arg1, arg2, (void*)arg3, arg4, arg5);
tswap32s((uint32_t*)arg3);
break;
+/* may need more translation if target arch is different from host */
+#if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
+ case -61:
+ DPRINTF("syscall_thread_switch(0x%x, 0x%x, 0x%x)\n",
+ arg1, arg2, arg3);
+ ret = syscall_thread_switch(arg1, arg2, arg3); // just a hint to the scheduler; can drop?
+ break;
+#endif
case -89:
DPRINTF("mach_timebase_info(0x%x)\n", arg1);
struct mach_timebase_info info;
@@ -1299,7 +1336,7 @@ static inline long bswap_syctl(int * mib, int count, void *buf, int size)
if(!(sysctl = sysctl->childs))
break;
}
-
+
if(ret->childs)
qerror("we shouldn't have a directory element\n");
@@ -1338,13 +1375,16 @@ long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, vo
//bswap_syctl(name, namelen, newp, newlen);
tswap32s((uint32_t*)oldlenp);
}
-
+
if(name) /* Sometimes sysctl is called with no arg1, ignore */
ret = get_errno(sysctl(name, namelen, oldp, oldlenp, newp, newlen));
+#if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
if (!is_error(ret) && bswap_syctl(name, namelen, oldp, *oldlenp) != 0) {
return -ENOTDIR;
}
+#endif
+
if(name) {
//bswap_syctl(name, namelen, newp, newlen);
tswap32s((uint32_t*)oldlenp);
diff --git a/darwin-user/syscalls.h b/darwin-user/syscalls.h
index 7c361ce59..34d95daa7 100644
--- a/darwin-user/syscalls.h
+++ b/darwin-user/syscalls.h
@@ -42,7 +42,7 @@
ENTRY("getppid", SYS_getppid, getppid, 0, CALL_DIRECT, VOID) /* 39 */
ENTRY("", 40, no_syscall, 0, CALL_INDIRECT, VOID) /* 40 old lstat */
ENTRY("dup", SYS_dup, dup, 1, CALL_DIRECT, INT) /* 41 */
- ENTRY("pipe", SYS_pipe, unimpl_unix_syscall, 0, CALL_INDIRECT, PTR) /* 42 */
+ ENTRY("pipe", SYS_pipe, pipe, 0, CALL_INDIRECT, PTR) /* 42 */
ENTRY("getegid", SYS_getegid, getegid, 0, CALL_NOERRNO, VOID) /* 43 */
ENTRY("profil", SYS_profil, profil, 4, CALL_DIRECT, PTR, SIZE, INT, INT) /* 44 */
ENTRY("ktrace", SYS_ktrace, no_syscall, 4, CALL_INDIRECT, VOID) /* 45 */
@@ -247,7 +247,7 @@
ENTRY("fsetxattr", SYS_fsetxattr, no_syscall, 6, CALL_INDIRECT, VOID) /* 237 */
ENTRY("removexattr", SYS_removexattr, no_syscall, 3, CALL_INDIRECT, VOID) /* 238 */
ENTRY("fremovexattr", SYS_fremovexattr, no_syscall, 3, CALL_INDIRECT, VOID) /* 239 */
- ENTRY("listxattr", SYS_listxattr, no_syscall, 4, CALL_INDIRECT, VOID) /* 240 */
+ ENTRY("listxattr", SYS_listxattr, listxattr, 4, CALL_INDIRECT, VOID) /* 240 */
ENTRY("flistxattr", SYS_flistxattr, no_syscall, 4, CALL_INDIRECT, VOID) /* 241 */
ENTRY("fsctl", SYS_fsctl, fsctl, 4, CALL_DIRECT, PTR, UINT, PTR, UINT) /* 242 */
ENTRY("initgroups", SYS_initgroups, unimpl_unix_syscall, 3, CALL_INDIRECT, UINT, PTR, INT) /* 243 */
diff --git a/dis-asm.h b/dis-asm.h
index 73b4380b7..bacd9c46b 100644
--- a/dis-asm.h
+++ b/dis-asm.h
@@ -44,7 +44,7 @@ enum bfd_flavour {
enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN };
-enum bfd_architecture
+enum bfd_architecture
{
bfd_arch_unknown, /* File arch not known */
bfd_arch_obscure, /* Arch known, not one of these */
@@ -67,14 +67,14 @@ enum bfd_architecture
#define bfd_mach_mcf5249 16
#define bfd_mach_mcf547x 17
#define bfd_mach_mcf548x 18
- bfd_arch_vax, /* DEC Vax */
+ bfd_arch_vax, /* DEC Vax */
bfd_arch_i960, /* Intel 960 */
/* The order of the following is important.
- lower number indicates a machine type that
+ lower number indicates a machine type that
only accepts a subset of the instructions
available to machines with higher numbers.
The exception is the "ca", which is
- incompatible with all other machines except
+ incompatible with all other machines except
"core". */
#define bfd_mach_i960_core 1
@@ -181,6 +181,7 @@ enum bfd_architecture
#define bfd_mach_sh4al_dsp 0x4d
#define bfd_mach_sh5 0x50
bfd_arch_alpha, /* Dec Alpha */
+#define bfd_mach_alpha 1
bfd_arch_arm, /* Advanced Risc Machines ARM */
#define bfd_mach_arm_2 1
#define bfd_mach_arm_2a 2
@@ -201,6 +202,8 @@ enum bfd_architecture
bfd_arch_mn10300, /* Matsushita MN10300 */
bfd_arch_last
};
+#define bfd_mach_s390_31 31
+#define bfd_mach_s390_64 64
typedef struct symbol_cache_entry
{
@@ -225,7 +228,7 @@ enum dis_insn_type {
dis_dref2 /* Two data references in instruction */
};
-/* This struct is passed into the instruction decoding routine,
+/* This struct is passed into the instruction decoding routine,
and is passed back out into each callback. The various fields are used
for conveying information from your main routine into your callbacks,
for passing information into the instruction decoders (such as the
@@ -377,6 +380,8 @@ extern int print_insn_d10v PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_v850 PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_tic30 PARAMS ((bfd_vma, disassemble_info*));
extern int print_insn_ppc PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_alpha PARAMS ((bfd_vma, disassemble_info*));
+extern int print_insn_s390 PARAMS ((bfd_vma, disassemble_info*));
#if 0
/* Fetch the disassembler for a given BFD, if that support is available. */
@@ -419,7 +424,7 @@ extern int generic_symbol_at_address
/* Call this macro to initialize only the internal variables for the
disassembler. Architecture dependent things such as byte order, or machine
variant are not touched by this macro. This makes things much easier for
- GDB which must initialize these things seperatly. */
+ GDB which must initialize these things separately. */
#define INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) \
(INFO).fprintf_func = (FPRINTF_FUNC), \
diff --git a/disas.c b/disas.c
index 297992798..ae20d37bc 100644
--- a/disas.c
+++ b/disas.c
@@ -134,10 +134,10 @@ print_insn_thumb1(bfd_vma pc, disassemble_info *info)
}
#endif
-/* Disassemble this for me please... (debugging). 'flags' has teh following
+/* Disassemble this for me please... (debugging). 'flags' has the following
values:
i386 - nonzero means 16 bit code
- arm - nonzero means thumb code
+ arm - nonzero means thumb code
ppc - nonzero means little endian
other targets - unused
*/
@@ -162,7 +162,7 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
#if defined(TARGET_I386)
if (flags == 2)
disasm_info.mach = bfd_mach_x86_64;
- else if (flags == 1)
+ else if (flags == 1)
disasm_info.mach = bfd_mach_i386_i8086;
else
disasm_info.mach = bfd_mach_i386_i386;
@@ -176,15 +176,20 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
print_insn = print_insn_sparc;
#ifdef TARGET_SPARC64
disasm_info.mach = bfd_mach_sparc_v9b;
-#endif
+#endif
#elif defined(TARGET_PPC)
- if (flags)
+ if (flags >> 16)
disasm_info.endian = BFD_ENDIAN_LITTLE;
+ if (flags & 0xFFFF) {
+ /* If we have a precise definitions of the instructions set, use it */
+ disasm_info.mach = flags & 0xFFFF;
+ } else {
#ifdef TARGET_PPC64
- disasm_info.mach = bfd_mach_ppc64;
+ disasm_info.mach = bfd_mach_ppc64;
#else
- disasm_info.mach = bfd_mach_ppc;
+ disasm_info.mach = bfd_mach_ppc;
#endif
+ }
print_insn = print_insn_ppc;
#elif defined(TARGET_M68K)
print_insn = print_insn_m68k;
@@ -197,6 +202,9 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
#elif defined(TARGET_SH4)
disasm_info.mach = bfd_mach_sh4;
print_insn = print_insn_sh;
+#elif defined(TARGET_ALPHA)
+ disasm_info.mach = bfd_mach_alpha;
+ print_insn = print_insn_alpha;
#else
fprintf(out, "0x" TARGET_FMT_lx
": Asm output not supported on this arch\n", code);
@@ -255,7 +263,10 @@ void disas(FILE *out, void *code, unsigned long size)
print_insn = print_insn_alpha;
#elif defined(__sparc__)
print_insn = print_insn_sparc;
-#elif defined(__arm__)
+#if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
+ disasm_info.mach = bfd_mach_sparc_v9b;
+#endif
+#elif defined(__arm__)
print_insn = print_insn_arm;
#elif defined(__MIPSEB__)
print_insn = print_insn_big_mips;
@@ -263,6 +274,8 @@ void disas(FILE *out, void *code, unsigned long size)
print_insn = print_insn_little_mips;
#elif defined(__m68k__)
print_insn = print_insn_m68k;
+#elif defined(__s390__)
+ print_insn = print_insn_s390;
#else
fprintf(out, "0x%lx: Asm output not supported on this arch\n",
(long) code);
@@ -290,7 +303,7 @@ const char *lookup_symbol(target_ulong orig_addr)
Elf32_Sym *sym;
struct syminfo *s;
target_ulong addr;
-
+
for (s = syminfos; s; s = s->next) {
sym = s->disas_symtab;
for (i = 0; i < s->disas_num_syms; i++) {
@@ -302,8 +315,8 @@ const char *lookup_symbol(target_ulong orig_addr)
continue;
addr = sym[i].st_value;
-#ifdef TARGET_ARM
- /* The bottom address bit marks a Thumb symbol. */
+#if defined(TARGET_ARM) || defined (TARGET_MIPS)
+ /* The bottom address bit marks a Thumb or MIPS16 symbol. */
addr &= ~(target_ulong)1;
#endif
if (orig_addr >= addr
@@ -369,7 +382,7 @@ void monitor_disas(CPUState *env,
#if defined(TARGET_I386)
if (flags == 2)
disasm_info.mach = bfd_mach_x86_64;
- else if (flags == 1)
+ else if (flags == 1)
disasm_info.mach = bfd_mach_i386_i8086;
else
disasm_info.mach = bfd_mach_i386_i386;
@@ -378,6 +391,9 @@ void monitor_disas(CPUState *env,
print_insn = print_insn_arm;
#elif defined(TARGET_SPARC)
print_insn = print_insn_sparc;
+#ifdef TARGET_SPARC64
+ disasm_info.mach = bfd_mach_sparc_v9b;
+#endif
#elif defined(TARGET_PPC)
#ifdef TARGET_PPC64
disasm_info.mach = bfd_mach_ppc64;
diff --git a/dyngen-exec.h b/dyngen-exec.h
index 7b313d62c..37c593e29 100644
--- a/dyngen-exec.h
+++ b/dyngen-exec.h
@@ -78,27 +78,30 @@ typedef void * host_reg_t;
#define UINT32_MAX (4294967295U)
#define UINT64_MAX ((uint64_t)(18446744073709551615))
+#ifdef _BSD
+typedef struct __sFILE FILE;
+#else
typedef struct FILE FILE;
+#endif
extern int fprintf(FILE *, const char *, ...);
+extern int fputs(const char *, FILE *);
extern int printf(const char *, ...);
#undef NULL
#define NULL 0
-#ifdef __i386__
+#if defined(__i386__)
#define AREG0 "ebp"
#define AREG1 "ebx"
#define AREG2 "esi"
#define AREG3 "edi"
-#endif
-#ifdef __x86_64__
-#define AREG0 "rbp"
-#define AREG1 "rbx"
+#elif defined(__x86_64__)
+#define AREG0 "r14"
+#define AREG1 "r15"
#define AREG2 "r12"
#define AREG3 "r13"
-//#define AREG4 "r14"
-//#define AREG5 "r15"
-#endif
-#ifdef __powerpc__
+//#define AREG4 "rbp"
+//#define AREG5 "rbx"
+#elif defined(__powerpc__)
#define AREG0 "r27"
#define AREG1 "r24"
#define AREG2 "r25"
@@ -116,20 +119,22 @@ extern int printf(const char *, ...);
#endif
#define USE_INT_TO_FLOAT_HELPERS
#define BUGGY_GCC_DIV64
-#endif
-#ifdef __arm__
+#elif defined(__arm__)
#define AREG0 "r7"
#define AREG1 "r4"
#define AREG2 "r5"
#define AREG3 "r6"
-#endif
-#ifdef __mips__
-#define AREG0 "s3"
+#elif defined(__mips__)
+#define AREG0 "fp"
#define AREG1 "s0"
#define AREG2 "s1"
#define AREG3 "s2"
-#endif
-#ifdef __sparc__
+#define AREG4 "s3"
+#define AREG5 "s4"
+#define AREG6 "s5"
+#define AREG7 "s6"
+#define AREG8 "s7"
+#elif defined(__sparc__)
#ifdef HOST_SOLARIS
#define AREG0 "g2"
#define AREG1 "g3"
@@ -158,14 +163,12 @@ extern int printf(const char *, ...);
#endif
#endif
#define USE_FP_CONVERT
-#endif
-#ifdef __s390__
+#elif defined(__s390__)
#define AREG0 "r10"
#define AREG1 "r7"
#define AREG2 "r8"
#define AREG3 "r9"
-#endif
-#ifdef __alpha__
+#elif defined(__alpha__)
/* Note $15 is the frame pointer, so anything in op-i386.c that would
require a frame pointer, like alloca, would probably loose. */
#define AREG0 "$15"
@@ -175,19 +178,19 @@ extern int printf(const char *, ...);
#define AREG4 "$12"
#define AREG5 "$13"
#define AREG6 "$14"
-#endif
-#ifdef __mc68000
+#elif defined(__mc68000)
#define AREG0 "%a5"
#define AREG1 "%a4"
#define AREG2 "%d7"
#define AREG3 "%d6"
#define AREG4 "%d5"
-#endif
-#ifdef __ia64__
+#elif defined(__ia64__)
#define AREG0 "r7"
#define AREG1 "r4"
#define AREG2 "r5"
#define AREG3 "r6"
+#else
+#error unsupported CPU
#endif
/* force GCC to generate only one epilog at the end of the function */
@@ -206,7 +209,7 @@ extern int printf(const char *, ...);
/* the symbols are considered non exported so a br immediate is generated */
#define __hidden __attribute__((visibility("hidden")))
#else
-#define __hidden
+#define __hidden
#endif
#if defined(__alpha__)
@@ -240,40 +243,37 @@ extern int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
#define ASM_NAME(x) #x
#endif
-#ifdef __i386__
+#if defined(__i386__)
#define EXIT_TB() asm volatile ("ret")
#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __x86_64__
+#elif defined(__x86_64__)
#define EXIT_TB() asm volatile ("ret")
#define GOTO_LABEL_PARAM(n) asm volatile ("jmp " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __powerpc__
+#elif defined(__powerpc__)
#define EXIT_TB() asm volatile ("blr")
#define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __s390__
+#elif defined(__s390__)
#define EXIT_TB() asm volatile ("br %r14")
-#define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __alpha__
+#define GOTO_LABEL_PARAM(n) asm volatile ("bras %r7,8; .long " ASM_NAME(__op_gen_label) #n "; l %r7, 0(%r7); br %r7")
+#elif defined(__alpha__)
#define EXIT_TB() asm volatile ("ret")
-#endif
-#ifdef __ia64__
+#elif defined(__ia64__)
#define EXIT_TB() asm volatile ("br.ret.sptk.many b0;;")
#define GOTO_LABEL_PARAM(n) asm volatile ("br.sptk.many " \
ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __sparc__
+#elif defined(__sparc__)
#define EXIT_TB() asm volatile ("jmpl %i0 + 8, %g0; nop")
#define GOTO_LABEL_PARAM(n) asm volatile ("ba " ASM_NAME(__op_gen_label) #n ";nop")
-#endif
-#ifdef __arm__
+#elif defined(__arm__)
#define EXIT_TB() asm volatile ("b exec_loop")
#define GOTO_LABEL_PARAM(n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)
-#endif
-#ifdef __mc68000
+#elif defined(__mc68000)
#define EXIT_TB() asm volatile ("rts")
+#elif defined(__mips__)
+#define EXIT_TB() asm volatile ("jr $ra")
+#define GOTO_LABEL_PARAM(n) asm volatile (".set noat; la $1, " ASM_NAME(__op_gen_label) #n "; jr $1; .set at")
+#else
+#error unsupported CPU
#endif
#endif /* !defined(__DYNGEN_EXEC_H__) */
diff --git a/dyngen.c b/dyngen.c
index bcfb86ea0..f136e02c2 100644
--- a/dyngen.c
+++ b/dyngen.c
@@ -1,6 +1,6 @@
/*
* Generic Dynamic compiler generator
- *
+ *
* Copyright (c) 2003 Fabrice Bellard
*
* The COFF object format support was extracted from Kazu's QEMU port
@@ -117,6 +117,21 @@
#define elf_check_arch(x) ((x) == EM_68K)
#define ELF_USES_RELOCA
+#elif defined(HOST_MIPS)
+
+#define ELF_CLASS ELFCLASS32
+#define ELF_ARCH EM_MIPS
+#define elf_check_arch(x) ((x) == EM_MIPS)
+#define ELF_USES_RELOC
+
+#elif defined(HOST_MIPS64)
+
+/* Assume n32 ABI here, which is ELF32. */
+#define ELF_CLASS ELFCLASS32
+#define ELF_ARCH EM_MIPS
+#define elf_check_arch(x) ((x) == EM_MIPS)
+#define ELF_USES_RELOCA
+
#else
#error unsupported CPU - please update the code
#endif
@@ -148,11 +163,11 @@ typedef uint64_t host_ulong;
#ifdef CONFIG_FORMAT_COFF
-#include "a.out.h"
-
typedef int32_t host_long;
typedef uint32_t host_ulong;
+#include "a.out.h"
+
#define FILENAMELEN 256
typedef struct coff_sym {
@@ -189,11 +204,11 @@ typedef uint32_t host_ulong;
struct nlist_extended
{
union {
- char *n_name;
- long n_strx;
+ char *n_name;
+ long n_strx;
} n_un;
- unsigned char n_type;
- unsigned char n_sect;
+ unsigned char n_type;
+ unsigned char n_sect;
short st_desc;
unsigned long st_value;
unsigned long st_size;
@@ -357,10 +372,10 @@ int elf_must_swap(struct elfhdr *h)
} swaptest;
swaptest.i = 1;
- return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
+ return (h->e_ident[EI_DATA] == ELFDATA2MSB) !=
(swaptest.b[0] == 0);
}
-
+
void elf_swap_ehdr(struct elfhdr *h)
{
swab16s(&h->e_type); /* Object file type */
@@ -413,7 +428,7 @@ void elf_swap_rel(ELF_RELOC *rel)
#endif
}
-struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
+struct elf_shdr *find_elf_section(struct elf_shdr *shdr, int shnum, const char *shstr,
const char *name)
{
int i;
@@ -438,7 +453,7 @@ int find_reloc(int sh_index)
for(i = 0; i < ehdr.e_shnum; i++) {
sec = &shdr[i];
- if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
+ if (sec->sh_type == SHT_RELOC && sec->sh_info == sh_index)
return i;
}
return 0;
@@ -468,11 +483,11 @@ int load_object(const char *filename)
ElfW(Sym) *sym;
char *shstr;
ELF_RELOC *rel;
-
+
fd = open(filename, O_RDONLY);
- if (fd < 0)
+ if (fd < 0)
error("can't open file '%s'", filename);
-
+
/* Read ELF header. */
if (read(fd, &ehdr, sizeof (ehdr)) != sizeof (ehdr))
error("unable to read file header");
@@ -509,7 +524,7 @@ int load_object(const char *filename)
/* read all section data */
sdata = malloc(sizeof(void *) * ehdr.e_shnum);
memset(sdata, 0, sizeof(void *) * ehdr.e_shnum);
-
+
for(i = 0;i < ehdr.e_shnum; i++) {
sec = &shdr[i];
if (sec->sh_type != SHT_NOBITS)
@@ -554,7 +569,7 @@ int load_object(const char *filename)
symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
strtab = (char *)sdata[symtab_sec->sh_link];
-
+
nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
if (do_swap) {
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
@@ -594,7 +609,7 @@ void sym_ent_name(struct external_syment *ext_sym, EXE_SYM *sym)
{
char *q;
int c, i, len;
-
+
if (ext_sym->e.e.e_zeroes != 0) {
q = sym->st_name;
for(i = 0; i < 8; i++) {
@@ -628,7 +643,7 @@ char *name_for_dotdata(struct coff_rel *rel)
if (sym->st_syment->e_scnum == data_shndx &&
text_data >= sym->st_value &&
text_data < sym->st_value + sym->st_size) {
-
+
return sym->st_name;
}
@@ -686,15 +701,15 @@ int load_object(const char *filename)
uint32_t *n_strtab;
EXE_SYM *sym;
EXE_RELOC *rel;
-
- fd = open(filename, O_RDONLY
+
+ fd = open(filename, O_RDONLY
#ifdef _WIN32
| O_BINARY
#endif
);
- if (fd < 0)
+ if (fd < 0)
error("can't open file '%s'", filename);
-
+
/* Read COFF header. */
if (read(fd, &fhdr, sizeof (fhdr)) != sizeof (fhdr))
error("unable to read file header");
@@ -707,11 +722,11 @@ int load_object(const char *filename)
/* read section headers */
shdr = load_data(fd, sizeof(struct external_filehdr) + fhdr.f_opthdr, fhdr.f_nscns * sizeof(struct external_scnhdr));
-
+
/* read all section data */
sdata = malloc(sizeof(void *) * fhdr.f_nscns);
memset(sdata, 0, sizeof(void *) * fhdr.f_nscns);
-
+
const char *p;
for(i = 0;i < fhdr.f_nscns; i++) {
sec = &shdr[i];
@@ -732,7 +747,7 @@ int load_object(const char *filename)
if (!data_sec)
error("could not find .data section");
coff_data_shndx = data_sec - shdr;
-
+
coff_symtab = load_data(fd, fhdr.f_symptr, fhdr.f_nsyms*SYMESZ);
for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
for(i=0;i<8;i++)
@@ -742,8 +757,8 @@ int load_object(const char *filename)
n_strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), STRTAB_SIZE);
- strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab);
-
+ strtab = load_data(fd, (fhdr.f_symptr + fhdr.f_nsyms*SYMESZ), *n_strtab);
+
nb_syms = fhdr.f_nsyms;
for (i = 0, ext_sym = coff_symtab; i < nb_syms; i++, ext_sym++) {
@@ -790,12 +805,12 @@ int load_object(const char *filename)
} else {
sym->st_size = 0;
}
-
+
sym->st_type = ext_sym->e_type;
sym->st_shndx = ext_sym->e_scnum;
}
-
+
/* find text relocations, if any */
sec = &shdr[coff_text_shndx];
coff_relocs = load_data(fd, sec->s_relptr, sec->s_nreloc*RELSZ);
@@ -803,7 +818,7 @@ int load_object(const char *filename)
/* set coff relocation */
relocs = malloc(sizeof(struct coff_rel) * nb_relocs);
- for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs;
+ for (i = 0, ext_rel = coff_relocs, rel = relocs; i < nb_relocs;
i++, ext_rel++, rel++) {
memset(rel, 0, sizeof(*rel));
rel->r_reloc = ext_rel;
@@ -832,7 +847,7 @@ uint8_t **sdata;
/* relocs */
struct relocation_info *relocs;
-
+
/* symbols */
EXE_SYM *symtab;
struct nlist *symtab_std;
@@ -852,10 +867,10 @@ static inline char *find_str_by_index(int index)
static char *get_sym_name(EXE_SYM *sym)
{
char *name = find_str_by_index(sym->n_un.n_strx);
-
+
if ( sym->n_type & N_STAB ) /* Debug symbols are ignored */
return "debug";
-
+
if(!name)
return name;
if(name[0]=='_')
@@ -865,7 +880,7 @@ static char *get_sym_name(EXE_SYM *sym)
}
/* find a section index given its segname, sectname */
-static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname,
+static int find_mach_sec_index(struct section *section_hdr, int shnum, const char *segname,
const char *sectname)
{
int i;
@@ -881,7 +896,7 @@ static int find_mach_sec_index(struct section *section_hdr, int shnum, const cha
}
/* find a section header given its segname, sectname */
-struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname,
+struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const char *segname,
const char *sectname)
{
int index = find_mach_sec_index(section_hdr, shnum, segname, sectname);
@@ -894,7 +909,7 @@ struct section *find_mach_sec_hdr(struct section *section_hdr, int shnum, const
static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned int *value)
{
struct scattered_relocation_info * scarel;
-
+
if(R_SCATTERED & rel->r_address) {
scarel = (struct scattered_relocation_info*)rel;
if(scarel->r_type != PPC_RELOC_PAIR)
@@ -911,7 +926,7 @@ static inline void fetch_next_pair_value(struct relocation_info * rel, unsigned
static const char * find_sym_with_value_and_sec_number( int value, int sectnum, int * offset )
{
int i, ret = -1;
-
+
for( i = 0 ; i < nb_syms; i++ )
{
if( !(symtab[i].n_type & N_STAB) && (symtab[i].n_type & N_SECT) &&
@@ -930,35 +945,35 @@ static const char * find_sym_with_value_and_sec_number( int value, int sectnum,
}
}
-/*
- * Find symbol name given a (virtual) address, and a section which is of type
+/*
+ * Find symbol name given a (virtual) address, and a section which is of type
* S_NON_LAZY_SYMBOL_POINTERS or S_LAZY_SYMBOL_POINTERS or S_SYMBOL_STUBS
*/
static const char * find_reloc_name_in_sec_ptr(int address, struct section * sec_hdr)
{
unsigned int tocindex, symindex, size;
const char *name = 0;
-
+
/* Sanity check */
if(!( address >= sec_hdr->addr && address < (sec_hdr->addr + sec_hdr->size) ) )
return (char*)0;
-
+
if( sec_hdr->flags & S_SYMBOL_STUBS ){
size = sec_hdr->reserved2;
if(size == 0)
error("size = 0");
-
+
}
else if( sec_hdr->flags & S_LAZY_SYMBOL_POINTERS ||
sec_hdr->flags & S_NON_LAZY_SYMBOL_POINTERS)
size = sizeof(unsigned long);
else
return 0;
-
+
/* Compute our index in toc */
tocindex = (address - sec_hdr->addr)/size;
symindex = tocdylib[sec_hdr->reserved1 + tocindex];
-
+
name = get_sym_name(&symtab[symindex]);
return name;
@@ -983,24 +998,24 @@ static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
int sectnum = rel->r_symbolnum;
int sectoffset;
int other_half=0;
-
+
/* init the slide value */
*sslide = 0;
-
+
if(R_SCATTERED & rel->r_address)
return (char *)find_reloc_name_given_its_address(sca_rel->r_value);
if(rel->r_extern)
{
/* ignore debug sym */
- if ( symtab[rel->r_symbolnum].n_type & N_STAB )
+ if ( symtab[rel->r_symbolnum].n_type & N_STAB )
return 0;
return get_sym_name(&symtab[rel->r_symbolnum]);
}
/* Intruction contains an offset to the symbols pointed to, in the rel->r_symbolnum section */
sectoffset = *(uint32_t *)(text + rel->r_address) & 0xffff;
-
+
if(sectnum==0xffffff)
return 0;
@@ -1026,14 +1041,14 @@ static const char * get_reloc_name(EXE_RELOC * rel, int * sslide)
if(rel->r_pcrel)
sectoffset += rel->r_address;
-
+
if (rel->r_type == PPC_RELOC_BR24)
name = (char *)find_reloc_name_in_sec_ptr((int)sectoffset, &section_hdr[sectnum-1]);
/* search it in the full symbol list, if not found */
if(!name)
name = (char *)find_sym_with_value_and_sec_number(sectoffset, sectnum, sslide);
-
+
return name;
}
@@ -1065,11 +1080,11 @@ int load_object(const char *filename)
unsigned int i, j;
EXE_SYM *sym;
struct nlist *syment;
-
+
fd = open(filename, O_RDONLY);
- if (fd < 0)
+ if (fd < 0)
error("can't open file '%s'", filename);
-
+
/* Read Mach header. */
if (read(fd, &mach_hdr, sizeof (mach_hdr)) != sizeof (mach_hdr))
error("unable to read file header");
@@ -1078,13 +1093,13 @@ int load_object(const char *filename)
if (!check_mach_header(mach_hdr)) {
error("bad Mach header");
}
-
+
if (mach_hdr.cputype != CPU_TYPE_POWERPC)
error("Unsupported CPU");
-
+
if (mach_hdr.filetype != MH_OBJECT)
error("Unsupported Mach Object");
-
+
/* read segment headers */
for(i=0, j=sizeof(mach_hdr); i<mach_hdr.ncmds ; i++)
{
@@ -1128,26 +1143,26 @@ int load_object(const char *filename)
/* read all section data */
sdata = (uint8_t **)malloc(sizeof(void *) * segment->nsects);
memset(sdata, 0, sizeof(void *) * segment->nsects);
-
+
/* Load the data in section data */
for(i = 0; i < segment->nsects; i++) {
sdata[i] = load_data(fd, section_hdr[i].offset, section_hdr[i].size);
}
-
+
/* text section */
text_sec_hdr = find_mach_sec_hdr(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
i = find_mach_sec_index(section_hdr, segment->nsects, SEG_TEXT, SECT_TEXT);
if (i == -1 || !text_sec_hdr)
error("could not find __TEXT,__text section");
text = sdata[i];
-
+
/* Make sure dysym was loaded */
if(!(int)dysymtabcmd)
error("could not find __DYSYMTAB segment");
-
+
/* read the table of content of the indirect sym */
tocdylib = load_data( fd, dysymtabcmd->indirectsymoff, dysymtabcmd->nindirectsyms * sizeof(uint32_t) );
-
+
/* Make sure symtab was loaded */
if(!(int)symtabcmd)
error("could not find __SYMTAB segment");
@@ -1155,20 +1170,20 @@ int load_object(const char *filename)
symtab_std = load_data(fd, symtabcmd->symoff, symtabcmd->nsyms * sizeof(struct nlist));
strtab = load_data(fd, symtabcmd->stroff, symtabcmd->strsize);
-
+
symtab = malloc(sizeof(EXE_SYM) * nb_syms);
-
+
/* Now transform the symtab, to an extended version, with the sym size, and the C name */
for(i = 0, sym = symtab, syment = symtab_std; i < nb_syms; i++, sym++, syment++) {
struct nlist *sym_follow, *sym_next = 0;
unsigned int j;
memset(sym, 0, sizeof(*sym));
-
+
if ( syment->n_type & N_STAB ) /* Debug symbols are skipped */
continue;
-
+
memcpy(sym, syment, sizeof(*syment));
-
+
/* Find the following symbol in order to get the current symbol size */
for(j = 0, sym_follow = symtab_std; j < nb_syms; j++, sym_follow++) {
if ( sym_follow->n_sect != 1 || sym_follow->n_type & N_STAB || !(sym_follow->n_value > sym->st_value))
@@ -1186,7 +1201,7 @@ int load_object(const char *filename)
else
sym->st_size = text_sec_hdr->size - sym->st_value;
}
-
+
/* Find Reloc */
relocs = load_data(fd, text_sec_hdr->reloff, text_sec_hdr->nreloc * sizeof(struct relocation_info));
nb_relocs = text_sec_hdr->nreloc;
@@ -1271,9 +1286,9 @@ int arm_emit_ldr_info(const char *name, unsigned long start_offset,
uint8_t data_allocated[1024];
unsigned int data_index;
int type;
-
+
memset(data_allocated, 0, sizeof(data_allocated));
-
+
p = p_start;
min_offset = p_end - p_start;
spare = 0x7fffffff;
@@ -1316,25 +1331,25 @@ int arm_emit_ldr_info(const char *name, unsigned long start_offset,
if (spare > max_pool - offset)
spare = max_pool - offset;
if ((offset & 3) !=0)
- error("%s:%04x: pc offset must be 32 bit aligned",
+ error("%s:%04x: pc offset must be 32 bit aligned",
name, start_offset + p - p_start);
if (offset < 0)
error("%s:%04x: Embedded literal value",
name, start_offset + p - p_start);
pc_offset = p - p_start + offset + 8;
- if (pc_offset <= (p - p_start) ||
+ if (pc_offset <= (p - p_start) ||
pc_offset >= (p_end - p_start))
- error("%s:%04x: pc offset must point inside the function code",
+ error("%s:%04x: pc offset must point inside the function code",
name, start_offset + p - p_start);
if (pc_offset < min_offset)
min_offset = pc_offset;
if (outfile) {
/* The intruction position */
- fprintf(outfile, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
+ fprintf(outfile, " arm_ldr_ptr->ptr = gen_code_ptr + %d;\n",
p - p_start);
/* The position of the constant pool data. */
data_index = ((p_end - p_start) - pc_offset) >> 2;
- fprintf(outfile, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
+ fprintf(outfile, " arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n",
data_index);
fprintf(outfile, " arm_ldr_ptr->type = %d;\n", type);
fprintf(outfile, " arm_ldr_ptr++;\n");
@@ -1417,7 +1432,7 @@ int arm_emit_ldr_info(const char *name, unsigned long start_offset,
#define MAX_ARGS 3
/* generate op code */
-void gen_code(const char *name, host_ulong offset, host_ulong size,
+void gen_code(const char *name, host_ulong offset, host_ulong size,
FILE *outfile, int gen_switch)
{
int copy_size = 0;
@@ -1463,7 +1478,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
copy_size = len;
}
-#endif
+#endif
#elif defined(HOST_PPC)
{
uint8_t *p;
@@ -1495,7 +1510,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
#endif
if (get32((uint32_t *)p) != 0x6bfa8001)
error("ret expected at the end of %s", name);
- copy_size = p - p_start;
+ copy_size = p - p_start;
}
#elif defined(HOST_IA64)
{
@@ -1596,14 +1611,14 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
} else {
error("No save at the beginning of %s", name);
}
-
+
/* Skip a preceeding nop, if present. */
if (p > p_start) {
skip_insn = get32((uint32_t *)(p - 0x4));
if (skip_insn == 0x01000000)
p -= 4;
}
-
+
copy_size = p - p_start;
}
#elif defined(HOST_ARM)
@@ -1624,7 +1639,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
p_start -= 4;
start_offset -= 4;
}
- copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
+ copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end,
relocs, nb_relocs);
}
#elif defined(HOST_M68K)
@@ -1635,12 +1650,32 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
error("empty code for %s", name);
// remove NOP's, probably added for alignment
while ((get16((uint16_t *)p) == 0x4e71) &&
- (p>p_start))
+ (p>p_start))
p -= 2;
if (get16((uint16_t *)p) != 0x4e75)
error("rts expected at the end of %s", name);
copy_size = p - p_start;
}
+#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
+ {
+#define INSN_RETURN 0x03e00008
+#define INSN_NOP 0x00000000
+
+ uint8_t *p = p_end;
+
+ if (p < (p_start + 0x8)) {
+ error("empty code for %s", name);
+ } else {
+ uint32_t end_insn1, end_insn2;
+
+ p -= 0x8;
+ end_insn1 = get32((uint32_t *)(p + 0x0));
+ end_insn2 = get32((uint32_t *)(p + 0x4));
+ if (end_insn1 != INSN_RETURN && end_insn2 != INSN_NOP)
+ error("jr ra not found at end of %s", name);
+ }
+ copy_size = p - p_start;
+ }
#else
#error unsupported CPU
#endif
@@ -1665,7 +1700,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
}
}
-
+
nb_args = 0;
while (nb_args < MAX_ARGS && args_present[nb_args])
nb_args++;
@@ -1702,7 +1737,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
sym_name = get_rel_sym_name(rel);
if(!sym_name)
continue;
- if (*sym_name &&
+ if (*sym_name &&
!strstart(sym_name, "__op_param", NULL) &&
!strstart(sym_name, "__op_jmp", NULL) &&
!strstart(sym_name, "__op_gen_label", NULL)) {
@@ -1715,8 +1750,9 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
#endif
#if defined(__APPLE__)
-/* set __attribute((unused)) on darwin because we wan't to avoid warning when we don't use the symbol */
- fprintf(outfile, "extern char %s __attribute__((unused));\n", sym_name);
+ /* Set __attribute((unused)) on darwin because we
+ want to avoid warning when we don't use the symbol. */
+ fprintf(outfile, " extern char %s __attribute__((unused));\n", sym_name);
#elif defined(HOST_IA64)
if (ELF64_R_TYPE(rel->r_info) != R_IA64_PCREL21B)
/*
@@ -1740,7 +1776,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
{
EXE_SYM *sym;
const char *sym_name, *p;
- unsigned long val;
+ host_ulong val;
int n;
for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
@@ -1748,7 +1784,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
if (strstart(sym_name, "__op_label", &p)) {
uint8_t *ptr;
unsigned long offset;
-
+
/* test if the variable refers to a label inside
the code we are generating */
#ifdef CONFIG_FORMAT_COFF
@@ -1772,7 +1808,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
#ifdef CONFIG_FORMAT_MACH
offset -= section_hdr[sym->n_sect-1].addr;
#endif
- val = *(unsigned long *)(ptr + offset);
+ val = *(host_ulong *)(ptr + offset);
#ifdef ELF_USES_RELOCA
{
int reloc_shndx, nb_relocs1, j;
@@ -1780,7 +1816,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
/* try to find a matching relocation */
reloc_shndx = find_reloc(sym->st_shndx);
if (reloc_shndx) {
- nb_relocs1 = shdr[reloc_shndx].sh_size /
+ nb_relocs1 = shdr[reloc_shndx].sh_size /
shdr[reloc_shndx].sh_entsize;
rel = (ELF_RELOC *)sdata[reloc_shndx];
for(j = 0; j < nb_relocs1; j++) {
@@ -1792,7 +1828,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
}
}
-#endif
+#endif
if (val >= start_offset && val <= start_offset + copy_size) {
n = strtol(p, NULL, 10);
fprintf(outfile, " label_offsets[%d] = %ld + (gen_code_ptr - gen_code_buf);\n", n, (long)(val - start_offset));
@@ -1801,7 +1837,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
}
- /* load parameres in variables */
+ /* load parameters in variables */
for(i = 0; i < nb_args; i++) {
fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1);
}
@@ -1809,7 +1845,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
/* patch relocations */
#if defined(HOST_I386)
{
- char name[256];
+ char relname[256];
int type;
int addend;
int reloc_offset;
@@ -1832,18 +1868,18 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
continue;
}
- get_reloc_expr(name, sizeof(name), sym_name);
+ get_reloc_expr(relname, sizeof(relname), sym_name);
addend = get32((uint32_t *)(text + rel->r_offset));
#ifdef CONFIG_FORMAT_ELF
type = ELF32_R_TYPE(rel->r_info);
switch(type) {
case R_386_32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
- reloc_offset, name, addend);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
+ reloc_offset, relname, addend);
break;
case R_386_PC32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
- reloc_offset, name, reloc_offset, addend);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
+ reloc_offset, relname, reloc_offset, addend);
break;
default:
error("unsupported i386 relocation (%d)", type);
@@ -1865,12 +1901,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
type = rel->r_type;
switch(type) {
case DIR32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
- reloc_offset, name, addend);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
+ reloc_offset, relname, addend);
break;
case DISP32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
- reloc_offset, name, reloc_offset, addend);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d -4;\n",
+ reloc_offset, relname, reloc_offset, addend);
break;
default:
error("unsupported i386 relocation (%d)", type);
@@ -1883,7 +1919,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
#elif defined(HOST_X86_64)
{
- char name[256];
+ char relname[256];
int type;
int addend;
int reloc_offset;
@@ -1891,22 +1927,22 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
if (rel->r_offset >= start_offset &&
rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
- get_reloc_expr(name, sizeof(name), sym_name);
+ get_reloc_expr(relname, sizeof(relname), sym_name);
type = ELF32_R_TYPE(rel->r_info);
addend = rel->r_addend;
reloc_offset = rel->r_offset - start_offset;
switch(type) {
case R_X86_64_32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
- reloc_offset, name, addend);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (uint32_t)%s + %d;\n",
+ reloc_offset, relname, addend);
break;
case R_X86_64_32S:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
- reloc_offset, name, addend);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (int32_t)%s + %d;\n",
+ reloc_offset, relname, addend);
break;
case R_X86_64_PC32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
- reloc_offset, name, reloc_offset, addend);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
+ reloc_offset, relname, reloc_offset, addend);
break;
default:
error("unsupported X86_64 relocation (%d)", type);
@@ -1917,7 +1953,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
#elif defined(HOST_PPC)
{
#ifdef CONFIG_FORMAT_ELF
- char name[256];
+ char relname[256];
int type;
int addend;
int reloc_offset;
@@ -1937,31 +1973,31 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
n, reloc_offset);
continue;
}
-
- get_reloc_expr(name, sizeof(name), sym_name);
+
+ get_reloc_expr(relname, sizeof(relname), sym_name);
type = ELF32_R_TYPE(rel->r_info);
addend = rel->r_addend;
switch(type) {
case R_PPC_ADDR32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
- reloc_offset, name, addend);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
+ reloc_offset, relname, addend);
break;
case R_PPC_ADDR16_LO:
- fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
- reloc_offset, name, addend);
+ fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
+ reloc_offset, relname, addend);
break;
case R_PPC_ADDR16_HI:
- fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
- reloc_offset, name, addend);
+ fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
+ reloc_offset, relname, addend);
break;
case R_PPC_ADDR16_HA:
- fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
- reloc_offset, name, addend);
+ fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
+ reloc_offset, relname, addend);
break;
case R_PPC_REL24:
/* warning: must be at 32 MB distancy */
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
- reloc_offset, reloc_offset, name, reloc_offset, addend);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
+ reloc_offset, reloc_offset, relname, reloc_offset, addend);
break;
default:
error("unsupported powerpc relocation (%d)", type);
@@ -1969,98 +2005,97 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
}
#elif defined(CONFIG_FORMAT_MACH)
- struct scattered_relocation_info *scarel;
- struct relocation_info * rel;
- char final_sym_name[256];
- const char *sym_name;
- const char *p;
- int slide, sslide;
- int i;
-
- for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
- unsigned int offset, length, value = 0;
- unsigned int type, pcrel, isym = 0;
- unsigned int usesym = 0;
-
- if(R_SCATTERED & rel->r_address) {
- scarel = (struct scattered_relocation_info*)rel;
- offset = (unsigned int)scarel->r_address;
- length = scarel->r_length;
- pcrel = scarel->r_pcrel;
- type = scarel->r_type;
- value = scarel->r_value;
- } else {
- value = isym = rel->r_symbolnum;
- usesym = (rel->r_extern);
- offset = rel->r_address;
- length = rel->r_length;
- pcrel = rel->r_pcrel;
- type = rel->r_type;
- }
-
- slide = offset - start_offset;
-
- if (!(offset >= start_offset && offset < start_offset + size))
- continue; /* not in our range */
-
- sym_name = get_reloc_name(rel, &sslide);
-
- if(usesym && symtab[isym].n_type & N_STAB)
- continue; /* don't handle STAB (debug sym) */
-
- if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
- int n;
- n = strtol(p, NULL, 10);
- fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
- n, slide);
- continue; /* Nothing more to do */
- }
-
- if(!sym_name)
- {
- fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
- name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
- continue; /* dunno how to handle without final_sym_name */
- }
-
- get_reloc_expr(final_sym_name, sizeof(final_sym_name),
- sym_name);
- switch(type) {
- case PPC_RELOC_BR24:
- if (!strstart(sym_name,"__op_gen_label",&p)) {
- fprintf(outfile, "{\n");
- fprintf(outfile, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((imm + ((long)%s - (long)gen_code_ptr) + %d) & 0x03fffffc);\n",
- slide, slide, name, sslide );
- fprintf(outfile, "}\n");
- } else {
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
- slide, slide, final_sym_name, slide);
- }
- break;
- case PPC_RELOC_HI16:
- fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
- slide, final_sym_name, sslide);
- break;
- case PPC_RELOC_LO16:
- fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
- slide, final_sym_name, sslide);
+ struct scattered_relocation_info *scarel;
+ struct relocation_info * rel;
+ char final_sym_name[256];
+ const char *sym_name;
+ const char *p;
+ int slide, sslide;
+ int i;
+
+ for(i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
+ unsigned int offset, length, value = 0;
+ unsigned int type, pcrel, isym = 0;
+ unsigned int usesym = 0;
+
+ if(R_SCATTERED & rel->r_address) {
+ scarel = (struct scattered_relocation_info*)rel;
+ offset = (unsigned int)scarel->r_address;
+ length = scarel->r_length;
+ pcrel = scarel->r_pcrel;
+ type = scarel->r_type;
+ value = scarel->r_value;
+ } else {
+ value = isym = rel->r_symbolnum;
+ usesym = (rel->r_extern);
+ offset = rel->r_address;
+ length = rel->r_length;
+ pcrel = rel->r_pcrel;
+ type = rel->r_type;
+ }
+
+ slide = offset - start_offset;
+
+ if (!(offset >= start_offset && offset < start_offset + size))
+ continue; /* not in our range */
+
+ sym_name = get_reloc_name(rel, &sslide);
+
+ if(usesym && symtab[isym].n_type & N_STAB)
+ continue; /* don't handle STAB (debug sym) */
+
+ if (sym_name && strstart(sym_name, "__op_jmp", &p)) {
+ int n;
+ n = strtol(p, NULL, 10);
+ fprintf(outfile, " jmp_offsets[%d] = %d + (gen_code_ptr - gen_code_buf);\n",
+ n, slide);
+ continue; /* Nothing more to do */
+ }
+
+ if(!sym_name) {
+ fprintf(outfile, "/* #warning relocation not handled in %s (value 0x%x, %s, offset 0x%x, length 0x%x, %s, type 0x%x) */\n",
+ name, value, usesym ? "use sym" : "don't use sym", offset, length, pcrel ? "pcrel":"", type);
+ continue; /* dunno how to handle without final_sym_name */
+ }
+
+ get_reloc_expr(final_sym_name, sizeof(final_sym_name),
+ sym_name);
+ switch(type) {
+ case PPC_RELOC_BR24:
+ if (!strstart(sym_name,"__op_gen_label",&p)) {
+ fprintf(outfile, "{\n");
+ fprintf(outfile, " uint32_t imm = *(uint32_t *)(gen_code_ptr + %d) & 0x3fffffc;\n", slide);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((imm + ((long)%s - (long)gen_code_ptr) + %d) & 0x03fffffc);\n",
+ slide, slide, name, sslide);
+ fprintf(outfile, "}\n");
+ } else {
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | (((long)%s - (long)gen_code_ptr - %d) & 0x03fffffc);\n",
+ slide, slide, final_sym_name, slide);
+ }
break;
- case PPC_RELOC_HA16:
- fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
- slide, final_sym_name, sslide);
- break;
- default:
- error("unsupported powerpc relocation (%d)", type);
- }
- }
+ case PPC_RELOC_HI16:
+ fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d) >> 16;\n",
+ slide, final_sym_name, sslide);
+ break;
+ case PPC_RELOC_LO16:
+ fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d);\n",
+ slide, final_sym_name, sslide);
+ break;
+ case PPC_RELOC_HA16:
+ fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d + 2) = (%s + %d + 0x8000) >> 16;\n",
+ slide, final_sym_name, sslide);
+ break;
+ default:
+ error("unsupported powerpc relocation (%d)", type);
+ }
+ }
#else
#error unsupport object format
#endif
}
#elif defined(HOST_S390)
{
- char name[256];
+ char relname[256];
int type;
int addend;
int reloc_offset;
@@ -2068,22 +2103,22 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
if (rel->r_offset >= start_offset &&
rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
- get_reloc_expr(name, sizeof(name), sym_name);
+ get_reloc_expr(relname, sizeof(relname), sym_name);
type = ELF32_R_TYPE(rel->r_info);
addend = rel->r_addend;
reloc_offset = rel->r_offset - start_offset;
switch(type) {
case R_390_32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
- reloc_offset, name, addend);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
+ reloc_offset, relname, addend);
break;
case R_390_16:
- fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
- reloc_offset, name, addend);
+ fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
+ reloc_offset, relname, addend);
break;
case R_390_8:
- fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
- reloc_offset, name, addend);
+ fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
+ reloc_offset, relname, addend);
break;
default:
error("unsupported s390 relocation (%d)", type);
@@ -2151,7 +2186,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
{
unsigned long sym_idx;
long code_offset;
- char name[256];
+ char relname[256];
int type;
long addend;
@@ -2174,7 +2209,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
n, code_offset);
continue;
}
- get_reloc_expr(name, sizeof(name), sym_name);
+ get_reloc_expr(relname, sizeof(relname), sym_name);
type = ELF64_R_TYPE(rel->r_info);
addend = rel->r_addend;
switch(type) {
@@ -2182,19 +2217,19 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
fprintf(outfile,
" ia64_imm64(gen_code_ptr + %ld, "
"%s + %ld);\n",
- code_offset, name, addend);
+ code_offset, relname, addend);
break;
case R_IA64_LTOFF22X:
case R_IA64_LTOFF22:
fprintf(outfile, " IA64_LTOFF(gen_code_ptr + %ld,"
" %s + %ld, %d);\n",
- code_offset, name, addend,
+ code_offset, relname, addend,
(type == R_IA64_LTOFF22X));
break;
case R_IA64_LDXMOV:
fprintf(outfile,
" ia64_ldxmov(gen_code_ptr + %ld,"
- " %s + %ld);\n", code_offset, name, addend);
+ " %s + %ld);\n", code_offset, relname, addend);
break;
case R_IA64_PCREL21B:
@@ -2203,7 +2238,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
" ia64_imm21b(gen_code_ptr + %ld,"
" (long) (%s + %ld -\n\t\t"
"((long) gen_code_ptr + %ld)) >> 4);\n",
- code_offset, name, addend,
+ code_offset, relname, addend,
code_offset & ~0xfUL);
} else {
fprintf(outfile,
@@ -2224,7 +2259,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
#elif defined(HOST_SPARC)
{
- char name[256];
+ char relname[256];
int type;
int addend;
int reloc_offset;
@@ -2232,14 +2267,14 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
if (rel->r_offset >= start_offset &&
rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
- get_reloc_expr(name, sizeof(name), sym_name);
+ get_reloc_expr(relname, sizeof(relname), sym_name);
type = ELF32_R_TYPE(rel->r_info);
addend = rel->r_addend;
reloc_offset = rel->r_offset - start_offset;
switch(type) {
case R_SPARC_32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
- reloc_offset, name, addend);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
+ reloc_offset, relname, addend);
break;
case R_SPARC_HI22:
fprintf(outfile,
@@ -2247,7 +2282,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
"((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3fffff) "
" | (((%s + %d) >> 10) & 0x3fffff);\n",
- reloc_offset, reloc_offset, name, addend);
+ reloc_offset, reloc_offset, relname, addend);
break;
case R_SPARC_LO10:
fprintf(outfile,
@@ -2255,7 +2290,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
"((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3ff) "
" | ((%s + %d) & 0x3ff);\n",
- reloc_offset, reloc_offset, name, addend);
+ reloc_offset, reloc_offset, relname, addend);
break;
case R_SPARC_WDISP30:
fprintf(outfile,
@@ -2264,7 +2299,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
" & ~0x3fffffff) "
" | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
" & 0x3fffffff);\n",
- reloc_offset, reloc_offset, name, addend,
+ reloc_offset, reloc_offset, relname, addend,
reloc_offset);
break;
case R_SPARC_WDISP22:
@@ -2276,7 +2311,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
" & 0x3fffff);\n",
rel->r_offset - start_offset,
rel->r_offset - start_offset,
- name, addend,
+ relname, addend,
rel->r_offset - start_offset);
break;
default:
@@ -2287,7 +2322,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
#elif defined(HOST_SPARC64)
{
- char name[256];
+ char relname[256];
int type;
int addend;
int reloc_offset;
@@ -2295,14 +2330,14 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
if (rel->r_offset >= start_offset &&
rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
- get_reloc_expr(name, sizeof(name), sym_name);
+ get_reloc_expr(relname, sizeof(relname), sym_name);
type = ELF32_R_TYPE(rel->r_info);
addend = rel->r_addend;
reloc_offset = rel->r_offset - start_offset;
switch(type) {
case R_SPARC_32:
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
- reloc_offset, name, addend);
+ reloc_offset, relname, addend);
break;
case R_SPARC_HI22:
fprintf(outfile,
@@ -2310,7 +2345,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
"((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3fffff) "
" | (((%s + %d) >> 10) & 0x3fffff);\n",
- reloc_offset, reloc_offset, name, addend);
+ reloc_offset, reloc_offset, relname, addend);
break;
case R_SPARC_LO10:
fprintf(outfile,
@@ -2318,7 +2353,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
"((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3ff) "
" | ((%s + %d) & 0x3ff);\n",
- reloc_offset, reloc_offset, name, addend);
+ reloc_offset, reloc_offset, relname, addend);
break;
case R_SPARC_OLO10:
addend += ELF64_R_TYPE_DATA (rel->r_info);
@@ -2327,7 +2362,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
"((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3ff) "
" | ((%s + %d) & 0x3ff);\n",
- reloc_offset, reloc_offset, name, addend);
+ reloc_offset, reloc_offset, relname, addend);
break;
case R_SPARC_WDISP30:
fprintf(outfile,
@@ -2336,7 +2371,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
" & ~0x3fffffff) "
" | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
" & 0x3fffffff);\n",
- reloc_offset, reloc_offset, name, addend,
+ reloc_offset, reloc_offset, relname, addend,
reloc_offset);
break;
case R_SPARC_WDISP22:
@@ -2346,18 +2381,45 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
" & ~0x3fffff) "
" | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
" & 0x3fffff);\n",
- reloc_offset, reloc_offset, name, addend,
+ reloc_offset, reloc_offset, relname, addend,
reloc_offset);
break;
+ case R_SPARC_HH22:
+ fprintf(outfile,
+ " *(uint32_t *)(gen_code_ptr + %d) = "
+ "((*(uint32_t *)(gen_code_ptr + %d)) "
+ " & ~0x00000000) "
+ " | (((%s + %d) >> 42) & 0x00000000);\n",
+ reloc_offset, reloc_offset, relname, addend);
+ break;
+
+ case R_SPARC_LM22:
+ fprintf(outfile,
+ " *(uint32_t *)(gen_code_ptr + %d) = "
+ "((*(uint32_t *)(gen_code_ptr + %d)) "
+ " & ~0x00000000) "
+ " | (((%s + %d) >> 10) & 0x00000000);\n",
+ reloc_offset, reloc_offset, relname, addend);
+ break;
+
+ case R_SPARC_HM10:
+ fprintf(outfile,
+ " *(uint32_t *)(gen_code_ptr + %d) = "
+ "((*(uint32_t *)(gen_code_ptr + %d)) "
+ " & ~0x00000000) "
+ " | ((((%s + %d) >> 32 & 0x3ff)) & 0x00000000);\n",
+ reloc_offset, reloc_offset, relname, addend);
+ break;
+
default:
- error("unsupported sparc64 relocation (%d) for symbol %s", type, name);
+ error("unsupported sparc64 relocation (%d) for symbol %s", type, relname);
}
}
}
}
#elif defined(HOST_ARM)
{
- char name[256];
+ char relname[256];
int type;
int addend;
int reloc_offset;
@@ -2392,7 +2454,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
fprintf(outfile,
" *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
}
- arm_emit_ldr_info(name, start_offset, outfile, p_start, p_end,
+ arm_emit_ldr_info(relname, start_offset, outfile, p_start, p_end,
relocs, nb_relocs);
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
@@ -2402,20 +2464,20 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
/* the compiler leave some unnecessary references to the code */
if (sym_name[0] == '\0')
continue;
- get_reloc_expr(name, sizeof(name), sym_name);
+ get_reloc_expr(relname, sizeof(relname), sym_name);
type = ELF32_R_TYPE(rel->r_info);
addend = get32((uint32_t *)(text + rel->r_offset));
reloc_offset = rel->r_offset - start_offset;
switch(type) {
case R_ARM_ABS32:
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
- reloc_offset, name, addend);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
+ reloc_offset, relname, addend);
break;
case R_ARM_PC24:
case R_ARM_JUMP24:
case R_ARM_CALL:
- fprintf(outfile, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
- reloc_offset, addend, name);
+ fprintf(outfile, " arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n",
+ reloc_offset, addend, relname);
break;
default:
error("unsupported arm relocation (%d)", type);
@@ -2425,7 +2487,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
#elif defined(HOST_M68K)
{
- char name[256];
+ char relname[256];
int type;
int addend;
int reloc_offset;
@@ -2435,20 +2497,20 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
rel->r_offset < start_offset + copy_size) {
sym = &(symtab[ELFW(R_SYM)(rel->r_info)]);
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
- get_reloc_expr(name, sizeof(name), sym_name);
+ get_reloc_expr(relname, sizeof(relname), sym_name);
type = ELF32_R_TYPE(rel->r_info);
addend = get32((uint32_t *)(text + rel->r_offset)) + rel->r_addend;
reloc_offset = rel->r_offset - start_offset;
switch(type) {
case R_68K_32:
fprintf(outfile, " /* R_68K_32 RELOC, offset %x */\n", rel->r_offset) ;
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
- reloc_offset, name, addend );
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %#x;\n",
+ reloc_offset, relname, addend );
break;
case R_68K_PC32:
fprintf(outfile, " /* R_68K_PC32 RELOC, offset %x */\n", rel->r_offset);
- fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
- reloc_offset, name, reloc_offset, /*sym->st_value+*/ addend);
+ fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %#x) + %#x;\n",
+ reloc_offset, relname, reloc_offset, /*sym->st_value+*/ addend);
break;
default:
error("unsupported m68k relocation (%d)", type);
@@ -2456,6 +2518,81 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
}
}
}
+#elif defined(HOST_MIPS) || defined(HOST_MIPS64)
+ {
+ for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
+ if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
+ char relname[256];
+ int type;
+ int addend;
+ int reloc_offset;
+
+ sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
+ /* the compiler leave some unnecessary references to the code */
+ if (sym_name[0] == '\0')
+ continue;
+ get_reloc_expr(relname, sizeof(relname), sym_name);
+ type = ELF32_R_TYPE(rel->r_info);
+ addend = get32((uint32_t *)(text + rel->r_offset));
+ reloc_offset = rel->r_offset - start_offset;
+ switch (type) {
+ case R_MIPS_26:
+ fprintf(outfile, " /* R_MIPS_26 RELOC, offset 0x%x, name %s */\n",
+ rel->r_offset, sym_name);
+ fprintf(outfile,
+ " *(uint32_t *)(gen_code_ptr + 0x%x) = "
+ "(0x%x & ~0x3fffff) "
+ "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
+ " & 0x3fffff);\n",
+ reloc_offset, addend, addend, relname, reloc_offset);
+ break;
+ case R_MIPS_HI16:
+ fprintf(outfile, " /* R_MIPS_HI16 RELOC, offset 0x%x, name %s */\n",
+ rel->r_offset, sym_name);
+ fprintf(outfile,
+ " *(uint32_t *)(gen_code_ptr + 0x%x) = "
+ "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
+ " & ~0xffff) "
+ " | (((%s - 0x8000) >> 16) & 0xffff);\n",
+ reloc_offset, reloc_offset, relname);
+ break;
+ case R_MIPS_LO16:
+ fprintf(outfile, " /* R_MIPS_LO16 RELOC, offset 0x%x, name %s */\n",
+ rel->r_offset, sym_name);
+ fprintf(outfile,
+ " *(uint32_t *)(gen_code_ptr + 0x%x) = "
+ "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
+ " & ~0xffff) "
+ " | (%s & 0xffff);\n",
+ reloc_offset, reloc_offset, relname);
+ break;
+ case R_MIPS_PC16:
+ fprintf(outfile, " /* R_MIPS_PC16 RELOC, offset 0x%x, name %s */\n",
+ rel->r_offset, sym_name);
+ fprintf(outfile,
+ " *(uint32_t *)(gen_code_ptr + 0x%x) = "
+ "(0x%x & ~0xffff) "
+ "| ((0x%x + ((%s - (*(uint32_t *)(gen_code_ptr + 0x%x))) >> 2)) "
+ " & 0xffff);\n",
+ reloc_offset, addend, addend, relname, reloc_offset);
+ break;
+ case R_MIPS_GOT16:
+ case R_MIPS_CALL16:
+ fprintf(outfile, " /* R_MIPS_GOT16 RELOC, offset 0x%x, name %s */\n",
+ rel->r_offset, sym_name);
+ fprintf(outfile,
+ " *(uint32_t *)(gen_code_ptr + 0x%x) = "
+ "((*(uint32_t *)(gen_code_ptr + 0x%x)) "
+ " & ~0xffff) "
+ " | (((%s - 0x8000) >> 16) & 0xffff);\n",
+ reloc_offset, reloc_offset, relname);
+ break;
+ default:
+ error("unsupported MIPS relocation (%d)", type);
+ }
+ }
+ }
+ }
#else
#error unsupported CPU
#endif
@@ -2515,7 +2652,7 @@ int gen_file(FILE *outfile, int out_type)
gen_code(name, sym->st_value, sym->st_size, outfile, 0);
}
}
-
+
} else {
/* generate big code generation switch */
@@ -2558,7 +2695,7 @@ fprintf(outfile,
eliminating the neeed to jump around the pool.
We currently generate:
-
+
[ For this example we assume merging would move op1_pool out of range.
In practice we should be able to combine many ops before the offset
limits are reached. ]
@@ -2645,7 +2782,7 @@ fprintf(outfile,
" opc_ptr = opc_buf;\n"
" opparam_ptr = opparam_buf;\n");
- /* Generate prologue, if needed. */
+ /* Generate prologue, if needed. */
fprintf(outfile,
" for(;;) {\n");
@@ -2671,7 +2808,7 @@ fprintf(outfile,
name = get_sym_name(sym);
if (strstart(name, OP_PREFIX, NULL)) {
#if 0
- printf("%4d: %s pos=0x%08x len=%d\n",
+ printf("%4d: %s pos=0x%08x len=%d\n",
i, name, sym->st_value, sym->st_size);
#endif
#if defined(CONFIG_FORMAT_ELF) || defined(CONFIG_FORMAT_COFF)
@@ -2713,7 +2850,7 @@ fprintf(outfile,
"plt_target, plt_offset);\n }\n");
#endif
-/* generate some code patching */
+/* generate some code patching */
#ifdef HOST_ARM
fprintf(outfile,
"if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
diff --git a/dyngen.h b/dyngen.h
index 2a87c448f..266b9e972 100644
--- a/dyngen.h
+++ b/dyngen.h
@@ -1,6 +1,6 @@
/*
* dyngen helpers
- *
+ *
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
@@ -28,25 +28,11 @@ int __op_param1, __op_param2, __op_param3;
#endif
int __op_jmp0, __op_jmp1, __op_jmp2, __op_jmp3;
-#ifdef __i386__
-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__
+#if defined(__i386__) || defined(__x86_64__) || defined(__s390__)
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
}
-#endif
-
-#ifdef __ia64__
+#elif defined(__ia64__)
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
while (start < stop) {
@@ -55,9 +41,7 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop)
}
asm volatile (";;sync.i;;srlz.i;;");
}
-#endif
-
-#ifdef __powerpc__
+#elif defined(__powerpc__)
#define MIN_CACHE_LINE_SIZE 8 /* conservative value */
@@ -67,7 +51,7 @@ static void inline flush_icache_range(unsigned long start, unsigned long stop)
start &= ~(MIN_CACHE_LINE_SIZE - 1);
stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
-
+
for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
}
@@ -78,17 +62,12 @@ static void inline flush_icache_range(unsigned long start, unsigned long stop)
asm volatile ("sync" : : : "memory");
asm volatile ("isync" : : : "memory");
}
-#endif
-
-#ifdef __alpha__
+#elif defined(__alpha__)
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
asm ("imb");
}
-#endif
-
-#ifdef __sparc__
-
+#elif defined(__sparc__)
static void inline flush_icache_range(unsigned long start, unsigned long stop)
{
unsigned long p;
@@ -99,10 +78,7 @@ static void inline flush_icache_range(unsigned long start, unsigned long stop)
for (; p < stop; p += 8)
__asm__ __volatile__("flush\t%0" : : "r" (p));
}
-
-#endif
-
-#ifdef __arm__
+#elif defined(__arm__)
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
register unsigned long _beg __asm ("a1") = start;
@@ -110,14 +86,22 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop)
register unsigned long _flg __asm ("a3") = 0;
__asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
}
-#endif
+#elif defined(__mc68000)
-#ifdef __mc68000
-#include <asm/cachectl.h>
+# 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);
}
+#elif defined(__mips__)
+
+#include <sys/cachectl.h>
+static inline void flush_icache_range(unsigned long start, unsigned long stop)
+{
+ _flush_cache ((void *)start, stop - start, BCACHE);
+}
+#else
+#error unsupported CPU
#endif
#ifdef __alpha__
@@ -164,8 +148,8 @@ static inline void arm_reloc_pc24(uint32_t *ptr, uint32_t insn, int val)
}
static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr,
- LDREntry *ldr_start, LDREntry *ldr_end,
- uint32_t *data_start, uint32_t *data_end,
+ LDREntry *ldr_start, LDREntry *ldr_end,
+ uint32_t *data_start, uint32_t *data_end,
int gen_jmp)
{
LDREntry *le;
@@ -174,7 +158,7 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr,
uint8_t *data_ptr;
uint32_t insn;
uint32_t mask;
-
+
data_size = (data_end - data_start) << 2;
if (gen_jmp) {
@@ -185,17 +169,17 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr,
arm_reloc_pc24((uint32_t *)gen_code_ptr, 0xeafffffe, target);
gen_code_ptr += 4;
}
-
+
/* copy the data */
data_ptr = gen_code_ptr;
memcpy(gen_code_ptr, data_start, data_size);
gen_code_ptr += data_size;
-
+
/* patch the ldr to point to the data */
for(le = ldr_start; le < ldr_end; le++) {
ptr = (uint32_t *)le->ptr;
- offset = ((unsigned long)(le->data_ptr) - (unsigned long)data_start) +
- (unsigned long)data_ptr -
+ offset = ((unsigned long)(le->data_ptr) - (unsigned long)data_start) +
+ (unsigned long)data_ptr -
(unsigned long)ptr - 8;
if (offset < 0) {
fprintf(stderr, "Negative constant pool offset\n");
@@ -248,7 +232,6 @@ static uint8_t *arm_flush_ldr(uint8_t *gen_code_ptr,
#ifdef __ia64
-
/* Patch instruction with "val" where "mask" has 1 bits. */
static inline void ia64_patch (uint64_t insn_addr, uint64_t mask, uint64_t val)
{
@@ -409,7 +392,8 @@ static inline void ia64_apply_fixes (uint8_t **gen_code_pp,
0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* nop 0; brl IP */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0
};
- uint8_t *gen_code_ptr = *gen_code_pp, *plt_start, *got_start, *vp;
+ uint8_t *gen_code_ptr = *gen_code_pp, *plt_start, *got_start;
+ uint64_t *vp;
struct ia64_fixup *fixup;
unsigned int offset = 0;
struct fdesc {
@@ -446,12 +430,12 @@ static inline void ia64_apply_fixes (uint8_t **gen_code_pp,
/* First, create the GOT: */
for (fixup = ltoff_fixes; fixup; fixup = fixup->next) {
/* first check if we already have this value in the GOT: */
- for (vp = got_start; vp < gen_code_ptr; ++vp)
- if (*(uint64_t *) vp == fixup->value)
+ for (vp = (uint64_t *) got_start; vp < (uint64_t *) gen_code_ptr; ++vp)
+ if (*vp == fixup->value)
break;
- if (vp == gen_code_ptr) {
+ if (vp == (uint64_t *) gen_code_ptr) {
/* Nope, we need to put the value in the GOT: */
- *(uint64_t *) vp = fixup->value;
+ *vp = fixup->value;
gen_code_ptr += 8;
}
ia64_imm22(fixup->addr, (long) vp - gp);
diff --git a/elf.h b/elf.h
index 1825d50e8..0c03f032a 100644
--- a/elf.h
+++ b/elf.h
@@ -328,6 +328,9 @@ typedef struct {
#define R_SPARC_11 31
#define R_SPARC_64 32
#define R_SPARC_OLO10 33
+#define R_SPARC_HH22 34
+#define R_SPARC_HM10 35
+#define R_SPARC_LM22 36
#define R_SPARC_WDISP16 40
#define R_SPARC_WDISP19 41
#define R_SPARC_7 43
@@ -1042,7 +1045,7 @@ typedef struct elf64_phdr {
#define SHN_COMMON 0xfff2
#define SHN_HIRESERVE 0xffff
#define SHN_MIPS_ACCOMON 0xff00
-
+
typedef struct elf32_shdr {
Elf32_Word sh_name;
Elf32_Word sh_type;
diff --git a/elf_ops.h b/elf_ops.h
index abcce093e..173d12f05 100644
--- a/elf_ops.h
+++ b/elf_ops.h
@@ -49,7 +49,7 @@ static void glue(bswap_sym, SZ)(struct elf_sym *sym)
bswap16s(&sym->st_shndx);
}
-static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table,
+static struct elf_shdr *glue(find_section, SZ)(struct elf_shdr *shdr_table,
int n, int type)
{
int i;
@@ -71,17 +71,17 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab)
int nsyms, i;
char *str = NULL;
- shdr_table = load_at(fd, ehdr->e_shoff,
+ shdr_table = load_at(fd, ehdr->e_shoff,
sizeof(struct elf_shdr) * ehdr->e_shnum);
if (!shdr_table)
return -1;
-
+
if (must_swab) {
for (i = 0; i < ehdr->e_shnum; i++) {
glue(bswap_shdr, SZ)(shdr_table + i);
}
}
-
+
symtab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_SYMTAB);
if (!symtab)
goto fail;
@@ -139,12 +139,14 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab)
}
int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend,
- int must_swab, uint64_t *pentry)
+ int must_swab, uint64_t *pentry,
+ uint64_t *lowaddr, uint64_t *highaddr)
{
struct elfhdr ehdr;
struct elf_phdr *phdr = NULL, *ph;
int size, i, total_size;
- elf_word mem_size, addr;
+ elf_word mem_size;
+ uint64_t addr, low = 0, high = 0;
uint8_t *data = NULL;
if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
@@ -174,7 +176,7 @@ int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend,
glue(bswap_phdr, SZ)(ph);
}
}
-
+
total_size = 0;
for(i = 0; i < ehdr.e_phnum; i++) {
ph = &phdr[i];
@@ -193,12 +195,20 @@ int glue(load_elf, SZ)(int fd, int64_t virt_to_phys_addend,
cpu_physical_memory_write_rom(addr, data, mem_size);
total_size += mem_size;
+ if (!low || addr < low)
+ low = addr;
+ if (!high || (addr + mem_size) > high)
+ high = addr + mem_size;
qemu_free(data);
data = NULL;
}
}
qemu_free(phdr);
+ if (lowaddr)
+ *lowaddr = (uint64_t)low;
+ if (highaddr)
+ *highaddr = (uint64_t)high;
return total_size;
fail:
qemu_free(data);
diff --git a/exec-all.h b/exec-all.h
index 82ef3acdc..dc5a10d97 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -1,6 +1,6 @@
/*
* internal execution defines for qemu
- *
+ *
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
@@ -28,10 +28,23 @@
#define tostring(s) #s
#endif
+#ifndef likely
#if __GNUC__ < 3
#define __builtin_expect(x, n) (x)
#endif
+#define likely(x) __builtin_expect(!!(x), 1)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+#endif
+
+#ifndef always_inline
+#if (__GNUC__ < 3) || defined(__APPLE__)
+#define always_inline inline
+#else
+#define always_inline __attribute__ (( always_inline )) inline
+#endif
+#endif
+
#ifdef __i386__
#define REGPARM(n) __attribute((regparm(n)))
#else
@@ -68,7 +81,7 @@ 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);
@@ -78,32 +91,35 @@ void optimize_flags_init(void);
extern FILE *logfile;
extern int loglevel;
+void muls64(int64_t *phigh, int64_t *plow, int64_t a, int64_t b);
+void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
+
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,
+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,
+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(CPUState *env);
int page_unprotect(target_ulong address, unsigned long pc, void *puc);
-void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
+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_exec(CPUState *env, target_ulong vaddr,
- target_phys_addr_t paddr, int prot,
+int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
+ target_phys_addr_t paddr, int prot,
int is_user, int is_softmmu);
-static inline int tlb_set_page(CPUState *env, target_ulong vaddr,
- target_phys_addr_t paddr, int prot,
+static inline int tlb_set_page(CPUState *env, target_ulong vaddr,
+ target_phys_addr_t paddr, int prot,
int is_user, int is_softmmu)
{
if (prot & PAGE_READ)
@@ -153,7 +169,7 @@ static inline int tlb_set_page(CPUState *env, target_ulong vaddr,
#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE)
-#if defined(__powerpc__)
+#if defined(__powerpc__)
#define USE_DIRECT_JUMP
#endif
#if defined(__i386__) && !defined(_WIN32)
@@ -163,7 +179,7 @@ static inline int tlb_set_page(CPUState *env, target_ulong vaddr,
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 */
+ uint64_t 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 */
@@ -174,11 +190,11 @@ typedef struct TranslationBlock {
uint8_t *tc_ptr; /* pointer to the translated code */
/* next matching tb for physical address. */
- struct TranslationBlock *phys_hash_next;
+ 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];
+ 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. */
@@ -192,7 +208,7 @@ typedef struct TranslationBlock {
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_next[2];
struct TranslationBlock *jmp_first;
} TranslationBlock;
@@ -218,7 +234,7 @@ static inline unsigned int tb_phys_hash_func(unsigned long pc)
TranslationBlock *tb_alloc(target_ulong pc);
void tb_flush(CPUState *env);
-void tb_link_phys(TranslationBlock *tb,
+void tb_link_phys(TranslationBlock *tb,
target_ulong phys_pc, target_ulong phys_page2);
extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
@@ -254,7 +270,7 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr
}
#endif
-static inline void tb_set_jmp_target(TranslationBlock *tb,
+static inline void tb_set_jmp_target(TranslationBlock *tb,
int n, unsigned long addr)
{
unsigned long offset;
@@ -269,7 +285,7 @@ static inline void tb_set_jmp_target(TranslationBlock *tb,
#else
/* set the jump target */
-static inline void tb_set_jmp_target(TranslationBlock *tb,
+static inline void tb_set_jmp_target(TranslationBlock *tb,
int n, unsigned long addr)
{
tb->tb_next[n] = addr;
@@ -277,14 +293,14 @@ static inline void tb_set_jmp_target(TranslationBlock *tb,
#endif
-static inline void tb_add_jump(TranslationBlock *tb, int n,
+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));
@@ -337,14 +353,32 @@ do {\
"1:\n");\
} while (0)
+#elif defined(__s390__)
+/* GCC spills R13, so we have to restore it before branching away */
+
+#define GOTO_TB(opname, tbparam, n)\
+do {\
+ static void __attribute__((used)) *dummy ## n = &&dummy_label ## n;\
+ static void __attribute__((used)) *__op_label ## n \
+ __asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\
+ __asm__ __volatile__ ( \
+ "l %%r13,52(%%r15)\n" \
+ "br %0\n" \
+ : : "r" (((TranslationBlock*)tbparam)->tb_next[n]));\
+ \
+ for(;*((int*)0);); /* just to keep GCC busy */ \
+label ## n: ;\
+dummy_label ## n: ;\
+} while(0)
+
#else
/* jump to next block operations (more portable code, does not need
cache flushing, but slower because of indirect jump) */
#define GOTO_TB(opname, tbparam, n)\
do {\
- static void __attribute__((unused)) *dummy ## n = &&dummy_label ## n;\
- static void __attribute__((unused)) *__op_label ## n \
+ static void __attribute__((used)) *dummy ## n = &&dummy_label ## n;\
+ static void __attribute__((used)) *__op_label ## n \
__asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\
goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
label ## n: ;\
@@ -357,7 +391,7 @@ 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__
+#if defined(__powerpc__)
static inline int testandset (int *p)
{
int ret;
@@ -373,35 +407,29 @@ static inline int testandset (int *p)
: "cr0", "memory");
return ret;
}
-#endif
-
-#ifdef __i386__
+#elif defined(__i386__)
static inline int testandset (int *p)
{
long int readval = 0;
-
+
__asm__ __volatile__ ("lock; cmpxchgl %2, %0"
: "+m" (*p), "+a" (readval)
: "r" (1)
: "cc");
return readval;
}
-#endif
-
-#ifdef __x86_64__
+#elif defined(__x86_64__)
static inline int testandset (int *p)
{
long int readval = 0;
-
+
__asm__ __volatile__ ("lock; cmpxchgl %2, %0"
: "+m" (*p), "+a" (readval)
: "r" (1)
: "cc");
return readval;
}
-#endif
-
-#ifdef __s390__
+#elif defined(__s390__)
static inline int testandset (int *p)
{
int ret;
@@ -409,13 +437,11 @@ static inline int testandset (int *p)
__asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
" jl 0b"
: "=&d" (ret)
- : "r" (1), "a" (p), "0" (*p)
+ : "r" (1), "a" (p), "0" (*p)
: "cc", "memory" );
return ret;
}
-#endif
-
-#ifdef __alpha__
+#elif defined(__alpha__)
static inline int testandset (int *p)
{
int ret;
@@ -432,9 +458,7 @@ static inline int testandset (int *p)
: "m" (*p));
return ret;
}
-#endif
-
-#ifdef __sparc__
+#elif defined(__sparc__)
static inline int testandset (int *p)
{
int ret;
@@ -446,21 +470,17 @@ static inline int testandset (int *p)
return (ret ? 1 : 0);
}
-#endif
-
-#ifdef __arm__
+#elif defined(__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
+#elif defined(__mc68000)
static inline int testandset (int *p)
{
char ret;
@@ -470,15 +490,36 @@ static inline int testandset (int *p)
: "cc","memory");
return ret;
}
-#endif
+#elif defined(__ia64)
-#ifdef __ia64
#include <ia64intrin.h>
static inline int testandset (int *p)
{
return __sync_lock_test_and_set (p, 1);
}
+#elif defined(__mips__)
+static inline int testandset (int *p)
+{
+ int ret;
+
+ __asm__ __volatile__ (
+ " .set push \n"
+ " .set noat \n"
+ " .set mips2 \n"
+ "1: li $1, 1 \n"
+ " ll %0, %1 \n"
+ " sc $1, %1 \n"
+ " beqz $1, 1b \n"
+ " .set pop "
+ : "=r" (ret), "+R" (*p)
+ :
+ : "memory");
+
+ return ret;
+}
+#else
+#error unimplemented CPU support
#endif
typedef int spinlock_t;
@@ -521,7 +562,7 @@ extern int tb_invalidated_flag;
#if !defined(CONFIG_USER_ONLY)
-void tlb_fill(target_ulong addr, int is_write, int is_user,
+void tlb_fill(target_ulong addr, int is_write, int is_user,
void *retaddr);
#define ACCESS_TYPE 3
@@ -572,22 +613,29 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
is_user = ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR);
#elif defined (TARGET_SH4)
is_user = ((env->sr & SR_MD) == 0);
+#elif defined (TARGET_ALPHA)
+ is_user = ((env->ps >> 3) & 3);
+#elif defined (TARGET_M68K)
+ is_user = ((env->sr & SR_S) == 0);
#else
#error unimplemented CPU
#endif
- if (__builtin_expect(env->tlb_table[is_user][index].addr_code !=
+ if (__builtin_expect(env->tlb_table[is_user][index].addr_code !=
(addr & TARGET_PAGE_MASK), 0)) {
ldub_code(addr);
}
pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK;
if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
- cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x%08lx\n", addr);
+#ifdef TARGET_SPARC
+ do_unassigned_access(addr, 0, 1, 0);
+#else
+ cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
+#endif
}
return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base;
}
#endif
-
#ifdef USE_KQEMU
#define KQEMU_MODIFY_PAGE_MASK (0xff & ~(VGA_DIRTY_FLAG | CODE_DIRTY_FLAG))
@@ -603,11 +651,11 @@ void kqemu_record_dump(void);
static inline int kqemu_is_ok(CPUState *env)
{
return(env->kqemu_enabled &&
- (env->cr[0] & CR0_PE_MASK) &&
+ (env->cr[0] & CR0_PE_MASK) &&
!(env->hflags & HF_INHIBIT_IRQ_MASK) &&
(env->eflags & IF_MASK) &&
!(env->eflags & VM_MASK) &&
- (env->kqemu_enabled == 2 ||
+ (env->kqemu_enabled == 2 ||
((env->hflags & HF_CPL_MASK) == 3 &&
(env->eflags & IOPL_MASK) != IOPL_MASK)));
}
diff --git a/exec.c b/exec.c
index ae2d825da..0c0b6542e 100644
--- a/exec.c
+++ b/exec.c
@@ -1,6 +1,6 @@
/*
* virtual page mapping and translated block handling
- *
+ *
* Copyright (c) 2003 Fabrice Bellard
*
* This library is free software; you can redistribute it and/or
@@ -44,8 +44,11 @@
//#define DEBUG_UNASSIGNED
/* make various TB consistency checks */
-//#define DEBUG_TB_CHECK
-//#define DEBUG_TLB_CHECK
+//#define DEBUG_TB_CHECK
+//#define DEBUG_TLB_CHECK
+
+//#define DEBUG_IOPORT
+//#define DEBUG_SUBPAGE
#if !defined(CONFIG_USER_ONLY)
/* TB consistency checks only implemented for usermode emulation. */
@@ -62,6 +65,11 @@
#if defined(TARGET_SPARC64)
#define TARGET_PHYS_ADDR_SPACE_BITS 41
+#elif defined(TARGET_SPARC)
+#define TARGET_PHYS_ADDR_SPACE_BITS 36
+#elif defined(TARGET_ALPHA)
+#define TARGET_PHYS_ADDR_SPACE_BITS 42
+#define TARGET_VIRT_ADDR_SPACE_BITS 42
#elif defined(TARGET_PPC64)
#define TARGET_PHYS_ADDR_SPACE_BITS 42
#else
@@ -82,11 +90,12 @@ int phys_ram_size;
int phys_ram_fd;
uint8_t *phys_ram_base;
uint8_t *phys_ram_dirty;
+static ram_addr_t phys_ram_alloc_offset = 0;
CPUState *first_cpu;
/* current CPU in the current thread. It is only valid inside
cpu_exec() */
-CPUState *cpu_single_env;
+CPUState *cpu_single_env;
typedef struct PageDesc {
/* list of TBs intersecting this ram page */
@@ -106,7 +115,15 @@ typedef struct PhysPageDesc {
} PhysPageDesc;
#define L2_BITS 10
+#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS)
+/* XXX: this is a temporary hack for alpha target.
+ * In the future, this is to be replaced by a multi-level table
+ * to actually be able to handle the complete 64 bits address space.
+ */
+#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS)
+#else
#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
+#endif
#define L1_SIZE (1 << L1_BITS)
#define L2_SIZE (1 << L2_BITS)
@@ -127,17 +144,29 @@ CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
void *io_mem_opaque[IO_MEM_NB_ENTRIES];
static int io_mem_nb;
+#if defined(CONFIG_SOFTMMU)
+static int io_mem_watch;
+#endif
/* log support */
char *logfilename = "/tmp/qemu.log";
FILE *logfile;
int loglevel;
+static int log_append = 0;
/* statistics */
static int tlb_flush_count;
static int tb_flush_count;
static int tb_phys_invalidate_count;
+#define SUBPAGE_IDX(addr) ((addr) & ~TARGET_PAGE_MASK)
+typedef struct subpage_t {
+ target_phys_addr_t base;
+ CPUReadMemoryFunc **mem_read[TARGET_PAGE_SIZE];
+ CPUWriteMemoryFunc **mem_write[TARGET_PAGE_SIZE];
+ void *opaque[TARGET_PAGE_SIZE];
+} subpage_t;
+
static void page_init(void)
{
/* NOTE: we can always suppose that qemu_host_page_size >=
@@ -146,10 +175,10 @@ static void page_init(void)
{
SYSTEM_INFO system_info;
DWORD old_protect;
-
+
GetSystemInfo(&system_info);
qemu_real_host_page_size = system_info.dwPageSize;
-
+
VirtualProtect(code_gen_buffer, sizeof(code_gen_buffer),
PAGE_EXECUTE_READWRITE, &old_protect);
}
@@ -160,12 +189,12 @@ static void page_init(void)
start = (unsigned long)code_gen_buffer;
start &= ~(qemu_real_host_page_size - 1);
-
+
end = (unsigned long)code_gen_buffer + sizeof(code_gen_buffer);
end += qemu_real_host_page_size - 1;
end &= ~(qemu_real_host_page_size - 1);
-
- mprotect((void *)start, end - start,
+
+ mprotect((void *)start, end - start,
PROT_READ | PROT_WRITE | PROT_EXEC);
}
#endif
@@ -251,7 +280,7 @@ static inline PhysPageDesc *phys_page_find(target_phys_addr_t index)
#if !defined(CONFIG_USER_ONLY)
static void tlb_protect_code(ram_addr_t ram_addr);
-static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
+static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
target_ulong vaddr);
#endif
@@ -273,6 +302,7 @@ void cpu_exec_init(CPUState *env)
cpu_index++;
}
env->cpu_index = cpu_index;
+ env->nb_watchpoints = 0;
*penv = env;
}
@@ -309,13 +339,13 @@ void tb_flush(CPUState *env1)
{
CPUState *env;
#if defined(DEBUG_FLUSH)
- printf("qemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n",
- code_gen_ptr - code_gen_buffer,
- nb_tbs,
+ printf("qemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n",
+ code_gen_ptr - code_gen_buffer,
+ nb_tbs,
nb_tbs > 0 ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0);
#endif
nb_tbs = 0;
-
+
for(env = first_cpu; env != NULL; env = env->next_cpu) {
memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
}
@@ -331,7 +361,7 @@ void tb_flush(CPUState *env1)
#ifdef DEBUG_TB_CHECK
-static void tb_invalidate_check(unsigned long address)
+static void tb_invalidate_check(target_ulong address)
{
TranslationBlock *tb;
int i;
@@ -352,7 +382,7 @@ static void tb_page_check(void)
{
TranslationBlock *tb;
int i, flags1, flags2;
-
+
for(i = 0;i < CODE_GEN_PHYS_HASH_SIZE; i++) {
for(tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
flags1 = page_get_flags(tb->pc);
@@ -461,11 +491,11 @@ static inline void tb_phys_invalidate(TranslationBlock *tb, unsigned int page_ad
unsigned int h, n1;
target_ulong phys_pc;
TranslationBlock *tb1, *tb2;
-
+
/* remove the TB from the hash list */
phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
h = tb_phys_hash_func(phys_pc);
- tb_remove(&tb_phys_hash[h], tb,
+ tb_remove(&tb_phys_hash[h], tb,
offsetof(TranslationBlock, phys_hash_next));
/* remove the TB from the page list */
@@ -541,7 +571,7 @@ static void build_page_bitmap(PageDesc *p)
{
int n, tb_start, tb_end;
TranslationBlock *tb;
-
+
p->code_bitmap = qemu_malloc(TARGET_PAGE_SIZE / 8);
if (!p->code_bitmap)
return;
@@ -570,7 +600,7 @@ static void build_page_bitmap(PageDesc *p)
#ifdef TARGET_HAS_PRECISE_SMC
-static void tb_gen_code(CPUState *env,
+static void tb_gen_code(CPUState *env,
target_ulong pc, target_ulong cs_base, int flags,
int cflags)
{
@@ -594,7 +624,7 @@ static void tb_gen_code(CPUState *env,
tb->cflags = cflags;
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 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
phys_page2 = -1;
@@ -604,13 +634,13 @@ static void tb_gen_code(CPUState *env,
tb_link_phys(tb, phys_pc, phys_page2);
}
#endif
-
+
/* invalidate all TBs which intersect with the target physical page
starting in range [start;end[. NOTE: start and end must refer to
the same physical page. 'is_cpu_write_access' should be true if called
from a real cpu write access: the virtual CPU will exit the current
TB if code is modified inside this TB. */
-void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
+void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
int is_cpu_write_access)
{
int n, current_tb_modified, current_tb_not_found, current_flags;
@@ -621,9 +651,9 @@ void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
target_ulong current_pc, current_cs_base;
p = page_find(start >> TARGET_PAGE_BITS);
- if (!p)
+ if (!p)
return;
- if (!p->code_bitmap &&
+ if (!p->code_bitmap &&
++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD &&
is_cpu_write_access) {
/* build code bitmap */
@@ -670,9 +700,9 @@ void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
that the modification is after the current PC, but it
would require a specialized function to partially
restore the CPU state */
-
+
current_tb_modified = 1;
- cpu_restore_state(current_tb, env,
+ cpu_restore_state(current_tb, env,
env->mem_write_pc, NULL);
#if defined(TARGET_I386)
current_flags = env->hflags;
@@ -715,7 +745,7 @@ void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
modifying the memory. It will ensure that it cannot modify
itself */
env->current_tb = NULL;
- tb_gen_code(env, current_pc, current_cs_base, current_flags,
+ tb_gen_code(env, current_pc, current_cs_base, current_flags,
CF_SINGLE_INSN);
cpu_resume_from_signal(env, NULL);
}
@@ -730,15 +760,15 @@ static inline void tb_invalidate_phys_page_fast(target_ulong start, int len)
#if 0
if (1) {
if (loglevel) {
- fprintf(logfile, "modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
- cpu_single_env->mem_write_vaddr, len,
- cpu_single_env->eip,
+ fprintf(logfile, "modifying code at 0x%x size=%d EIP=%x PC=%08x\n",
+ cpu_single_env->mem_write_vaddr, len,
+ cpu_single_env->eip,
cpu_single_env->eip + (long)cpu_single_env->segs[R_CS].base);
}
}
#endif
p = page_find(start >> TARGET_PAGE_BITS);
- if (!p)
+ if (!p)
return;
if (p->code_bitmap) {
offset = start & ~TARGET_PAGE_MASK;
@@ -752,7 +782,7 @@ static inline void tb_invalidate_phys_page_fast(target_ulong start, int len)
}
#if !defined(CONFIG_SOFTMMU)
-static void tb_invalidate_phys_page(target_ulong addr,
+static void tb_invalidate_phys_page(target_ulong addr,
unsigned long pc, void *puc)
{
int n, current_flags, current_tb_modified;
@@ -765,7 +795,7 @@ static void tb_invalidate_phys_page(target_ulong addr,
addr &= TARGET_PAGE_MASK;
p = page_find(addr >> TARGET_PAGE_BITS);
- if (!p)
+ if (!p)
return;
tb = p->first_tb;
current_tb_modified = 0;
@@ -789,7 +819,7 @@ static void tb_invalidate_phys_page(target_ulong addr,
that the modification is after the current PC, but it
would require a specialized function to partially
restore the CPU state */
-
+
current_tb_modified = 1;
cpu_restore_state(current_tb, env, pc, puc);
#if defined(TARGET_I386)
@@ -812,7 +842,7 @@ static void tb_invalidate_phys_page(target_ulong addr,
modifying the memory. It will ensure that it cannot modify
itself */
env->current_tb = NULL;
- tb_gen_code(env, current_pc, current_cs_base, current_flags,
+ tb_gen_code(env, current_pc, current_cs_base, current_flags,
CF_SINGLE_INSN);
cpu_resume_from_signal(env, puc);
}
@@ -821,7 +851,7 @@ static void tb_invalidate_phys_page(target_ulong addr,
#endif
/* add the tb in the target page and protect it if necessary */
-static inline void tb_alloc_page(TranslationBlock *tb,
+static inline void tb_alloc_page(TranslationBlock *tb,
unsigned int n, target_ulong page_addr)
{
PageDesc *p;
@@ -856,10 +886,10 @@ static inline void tb_alloc_page(TranslationBlock *tb,
p2->flags &= ~PAGE_WRITE;
page_get_flags(addr);
}
- mprotect(g2h(page_addr), qemu_host_page_size,
+ mprotect(g2h(page_addr), qemu_host_page_size,
(prot & PAGE_BITS) & ~PAGE_WRITE);
#ifdef DEBUG_TB_INVALIDATE
- printf("protecting code page: 0x%08lx\n",
+ printf("protecting code page: 0x%08lx\n",
page_addr);
#endif
}
@@ -881,7 +911,7 @@ TranslationBlock *tb_alloc(target_ulong pc)
{
TranslationBlock *tb;
- if (nb_tbs >= CODE_GEN_MAX_BLOCKS ||
+ if (nb_tbs >= CODE_GEN_MAX_BLOCKS ||
(code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
return NULL;
tb = &tbs[nb_tbs++];
@@ -892,7 +922,7 @@ TranslationBlock *tb_alloc(target_ulong pc)
/* add a new TB and link it to the physical page tables. phys_page2 is
(-1) to indicate that only one page contains the TB. */
-void tb_link_phys(TranslationBlock *tb,
+void tb_link_phys(TranslationBlock *tb,
target_ulong phys_pc, target_ulong phys_page2)
{
unsigned int h;
@@ -958,7 +988,7 @@ TranslationBlock *tb_find_pc(unsigned long tc_ptr)
} else {
m_min = m + 1;
}
- }
+ }
return &tbs[m_max];
}
@@ -994,7 +1024,7 @@ static inline void tb_reset_jump_recursive2(TranslationBlock *tb, int n)
}
*ptb = tb->jmp_next[n];
tb->jmp_next[n] = NULL;
-
+
/* suppress the jump to next tb in generated code */
tb_reset_jump(tb, n);
@@ -1012,7 +1042,8 @@ static void tb_reset_jump_recursive(TranslationBlock *tb)
#if defined(TARGET_HAS_ICE)
static void breakpoint_invalidate(CPUState *env, target_ulong pc)
{
- target_ulong addr, pd;
+ target_phys_addr_t addr;
+ target_ulong pd;
ram_addr_t ram_addr;
PhysPageDesc *p;
@@ -1028,13 +1059,51 @@ static void breakpoint_invalidate(CPUState *env, target_ulong pc)
}
#endif
+/* Add a watchpoint. */
+int cpu_watchpoint_insert(CPUState *env, target_ulong addr)
+{
+ int i;
+
+ for (i = 0; i < env->nb_watchpoints; i++) {
+ if (addr == env->watchpoint[i].vaddr)
+ return 0;
+ }
+ if (env->nb_watchpoints >= MAX_WATCHPOINTS)
+ return -1;
+
+ i = env->nb_watchpoints++;
+ env->watchpoint[i].vaddr = addr;
+ tlb_flush_page(env, addr);
+ /* FIXME: This flush is needed because of the hack to make memory ops
+ terminate the TB. It can be removed once the proper IO trap and
+ re-execute bits are in. */
+ tb_flush(env);
+ return i;
+}
+
+/* Remove a watchpoint. */
+int cpu_watchpoint_remove(CPUState *env, target_ulong addr)
+{
+ int i;
+
+ for (i = 0; i < env->nb_watchpoints; i++) {
+ if (addr == env->watchpoint[i].vaddr) {
+ env->nb_watchpoints--;
+ env->watchpoint[i] = env->watchpoint[env->nb_watchpoints];
+ tlb_flush_page(env, addr);
+ return 0;
+ }
+ }
+ return -1;
+}
+
/* add a breakpoint. EXCP_DEBUG is returned by the CPU loop if a
breakpoint is reached */
int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
{
#if defined(TARGET_HAS_ICE)
int i;
-
+
for(i = 0; i < env->nb_breakpoints; i++) {
if (env->breakpoints[i] == pc)
return 0;
@@ -1043,7 +1112,7 @@ int cpu_breakpoint_insert(CPUState *env, target_ulong pc)
if (env->nb_breakpoints >= MAX_BREAKPOINTS)
return -1;
env->breakpoints[env->nb_breakpoints++] = pc;
-
+
breakpoint_invalidate(env, pc);
return 0;
#else
@@ -1092,7 +1161,7 @@ void cpu_set_log(int log_flags)
{
loglevel = log_flags;
if (loglevel && !logfile) {
- logfile = fopen(logfilename, "w");
+ logfile = fopen(logfilename, log_append ? "a" : "w");
if (!logfile) {
perror(logfilename);
_exit(1);
@@ -1106,12 +1175,22 @@ void cpu_set_log(int log_flags)
#else
setvbuf(logfile, NULL, _IOLBF, 0);
#endif
+ log_append = 1;
+ }
+ if (!loglevel && logfile) {
+ fclose(logfile);
+ logfile = NULL;
}
}
void cpu_set_log_filename(const char *filename)
{
logfilename = strdup(filename);
+ if (logfile) {
+ fclose(logfile);
+ logfile = NULL;
+ }
+ cpu_set_log(loglevel);
}
/* mask must never be zero, except for A20 change call */
@@ -1137,11 +1216,11 @@ void cpu_reset_interrupt(CPUState *env, int mask)
}
CPULogItem cpu_log_items[] = {
- { CPU_LOG_TB_OUT_ASM, "out_asm",
+ { CPU_LOG_TB_OUT_ASM, "out_asm",
"show generated host assembly code for each compiled TB" },
{ CPU_LOG_TB_IN_ASM, "in_asm",
"show target assembly code for each compiled TB" },
- { CPU_LOG_TB_OP, "op",
+ { CPU_LOG_TB_OP, "op",
"show micro ops for each compiled TB (only usable if 'in_asm' used)" },
#ifdef TARGET_I386
{ CPU_LOG_TB_OP_OPT, "op_opt",
@@ -1152,7 +1231,7 @@ CPULogItem cpu_log_items[] = {
{ CPU_LOG_EXEC, "exec",
"show trace before each executed TB (lots of logs)" },
{ CPU_LOG_TB_CPU, "cpu",
- "show CPU state before bloc translation" },
+ "show CPU state before block translation" },
#ifdef TARGET_I386
{ CPU_LOG_PCALL, "pcall",
"show protected mode far calls/returns/exceptions" },
@@ -1170,7 +1249,7 @@ static int cmp1(const char *s1, int n, const char *s2)
return 0;
return memcmp(s1, s2, n) == 0;
}
-
+
/* takes a comma separated list of log masks. Return 0 if error. */
int cpu_str_to_log_mask(const char *str)
{
@@ -1213,14 +1292,43 @@ void cpu_abort(CPUState *env, const char *fmt, ...)
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
#ifdef TARGET_I386
+ if(env->intercept & INTERCEPT_SVM_MASK) {
+ /* most probably the virtual machine should not
+ be shut down but rather caught by the VMM */
+ vmexit(SVM_EXIT_SHUTDOWN, 0);
+ }
cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
#else
cpu_dump_state(env, stderr, fprintf, 0);
#endif
+ if (logfile) {
+ fprintf(logfile, "qemu: fatal: ");
+ vfprintf(logfile, fmt, ap);
+ fprintf(logfile, "\n");
+#ifdef TARGET_I386
+ cpu_dump_state(env, logfile, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP);
+#else
+ cpu_dump_state(env, logfile, fprintf, 0);
+#endif
+ fflush(logfile);
+ fclose(logfile);
+ }
va_end(ap);
abort();
}
+CPUState *cpu_copy(CPUState *env)
+{
+ CPUState *new_env = cpu_init();
+ /* preserve chaining and index */
+ CPUState *next_cpu = new_env->next_cpu;
+ int cpu_index = new_env->cpu_index;
+ memcpy(new_env, env, sizeof(CPUState));
+ new_env->next_cpu = next_cpu;
+ new_env->cpu_index = cpu_index;
+ return new_env;
+}
+
#if !defined(CONFIG_USER_ONLY)
/* NOTE: if flush_global is true, also flush global entries (not
@@ -1243,6 +1351,16 @@ void tlb_flush(CPUState *env, int flush_global)
env->tlb_table[1][i].addr_read = -1;
env->tlb_table[1][i].addr_write = -1;
env->tlb_table[1][i].addr_code = -1;
+#if (NB_MMU_MODES >= 3)
+ env->tlb_table[2][i].addr_read = -1;
+ env->tlb_table[2][i].addr_write = -1;
+ env->tlb_table[2][i].addr_code = -1;
+#if (NB_MMU_MODES == 4)
+ env->tlb_table[3][i].addr_read = -1;
+ env->tlb_table[3][i].addr_write = -1;
+ env->tlb_table[3][i].addr_code = -1;
+#endif
+#endif
}
memset (env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof (void *));
@@ -1260,11 +1378,11 @@ void tlb_flush(CPUState *env, int flush_global)
static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr)
{
- if (addr == (tlb_entry->addr_read &
+ if (addr == (tlb_entry->addr_read &
(TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
- addr == (tlb_entry->addr_write &
+ addr == (tlb_entry->addr_write &
(TARGET_PAGE_MASK | TLB_INVALID_MASK)) ||
- addr == (tlb_entry->addr_code &
+ addr == (tlb_entry->addr_code &
(TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
tlb_entry->addr_read = -1;
tlb_entry->addr_write = -1;
@@ -1288,6 +1406,12 @@ void tlb_flush_page(CPUState *env, target_ulong addr)
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
tlb_flush_entry(&env->tlb_table[0][i], addr);
tlb_flush_entry(&env->tlb_table[1][i], addr);
+#if (NB_MMU_MODES >= 3)
+ tlb_flush_entry(&env->tlb_table[2][i], addr);
+#if (NB_MMU_MODES == 4)
+ tlb_flush_entry(&env->tlb_table[3][i], addr);
+#endif
+#endif
/* Discard jump cache entries for any tb which might potentially
overlap the flushed page. */
@@ -1312,20 +1436,20 @@ void tlb_flush_page(CPUState *env, target_ulong addr)
can be detected */
static void tlb_protect_code(ram_addr_t ram_addr)
{
- cpu_physical_memory_reset_dirty(ram_addr,
+ cpu_physical_memory_reset_dirty(ram_addr,
ram_addr + TARGET_PAGE_SIZE,
CODE_DIRTY_FLAG);
}
/* update the TLB so that writes in physical page 'phys_addr' are no longer
tested for self modifying code */
-static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
+static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr,
target_ulong vaddr)
{
phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] |= CODE_DIRTY_FLAG;
}
-static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
+static inline void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
unsigned long start, unsigned long length)
{
unsigned long addr;
@@ -1377,6 +1501,14 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
tlb_reset_dirty_range(&env->tlb_table[0][i], start1, length);
for(i = 0; i < CPU_TLB_SIZE; i++)
tlb_reset_dirty_range(&env->tlb_table[1][i], start1, length);
+#if (NB_MMU_MODES >= 3)
+ for(i = 0; i < CPU_TLB_SIZE; i++)
+ tlb_reset_dirty_range(&env->tlb_table[2][i], start1, length);
+#if (NB_MMU_MODES == 4)
+ for(i = 0; i < CPU_TLB_SIZE; i++)
+ tlb_reset_dirty_range(&env->tlb_table[3][i], start1, length);
+#endif
+#endif
}
#if !defined(CONFIG_SOFTMMU)
@@ -1395,7 +1527,7 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
p->phys_addr >= start && p->phys_addr < end &&
(p->prot & PROT_WRITE)) {
if (addr < MMAP_AREA_END) {
- mprotect((void *)addr, TARGET_PAGE_SIZE,
+ mprotect((void *)addr, TARGET_PAGE_SIZE,
p->prot & ~PROT_WRITE);
}
}
@@ -1413,7 +1545,7 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry)
ram_addr_t ram_addr;
if ((tlb_entry->addr_write & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
- ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) +
+ ram_addr = (tlb_entry->addr_write & TARGET_PAGE_MASK) +
tlb_entry->addend - (unsigned long)phys_ram_base;
if (!cpu_physical_memory_is_dirty(ram_addr)) {
tlb_entry->addr_write |= IO_MEM_NOTDIRTY;
@@ -1429,9 +1561,17 @@ void cpu_tlb_update_dirty(CPUState *env)
tlb_update_dirty(&env->tlb_table[0][i]);
for(i = 0; i < CPU_TLB_SIZE; i++)
tlb_update_dirty(&env->tlb_table[1][i]);
+#if (NB_MMU_MODES >= 3)
+ for(i = 0; i < CPU_TLB_SIZE; i++)
+ tlb_update_dirty(&env->tlb_table[2][i]);
+#if (NB_MMU_MODES == 4)
+ for(i = 0; i < CPU_TLB_SIZE; i++)
+ tlb_update_dirty(&env->tlb_table[3][i]);
+#endif
+#endif
}
-static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry,
+static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry,
unsigned long start)
{
unsigned long addr;
@@ -1454,14 +1594,20 @@ static inline void tlb_set_dirty(CPUState *env,
i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
tlb_set_dirty1(&env->tlb_table[0][i], addr);
tlb_set_dirty1(&env->tlb_table[1][i], addr);
+#if (NB_MMU_MODES >= 3)
+ tlb_set_dirty1(&env->tlb_table[2][i], addr);
+#if (NB_MMU_MODES == 4)
+ tlb_set_dirty1(&env->tlb_table[3][i], addr);
+#endif
+#endif
}
/* add a new TLB entry. At most one entry for a given virtual address
is permitted. Return 0 if OK or 2 if the page could not be mapped
(can only happen in non SOFTMMU mode for I/O pages or pages
conflicting with the host address space). */
-int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
- target_phys_addr_t paddr, int prot,
+int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
+ target_phys_addr_t paddr, int prot,
int is_user, int is_softmmu)
{
PhysPageDesc *p;
@@ -1471,6 +1617,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
target_phys_addr_t addend;
int ret;
CPUTLBEntry *te;
+ int i;
p = phys_page_find(paddr >> TARGET_PAGE_BITS);
if (!p) {
@@ -1485,7 +1632,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
ret = 0;
#if !defined(CONFIG_SOFTMMU)
- if (is_softmmu)
+ if (is_softmmu)
#endif
{
if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
@@ -1497,7 +1644,24 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr,
address = vaddr;
addend = (unsigned long)phys_ram_base + (pd & TARGET_PAGE_MASK);
}
-
+