[Spice-commits] 188 commits - CODING_STYLE MAINTAINERS Makefile Makefile.objs Makefile.target arm-dis.c audio/alsaaudio.c audio/audio.c audio/audio_int.h audio/dsoundaudio.c audio/esdaudio.c audio/fmodaudio.c audio/mixeng.c audio/mixeng.h audio/mixeng_template.h audio/ossaudio.c audio/paaudio.c audio/spiceaudio.c audio/winwaveaudio.c block/vpc.c block/vvfat.c bsd-user/elfload.c cache-utils.h cmd.h configure create_config dis-asm.h disas.c docs/qdev-device-use.txt docs/specs envlist.h exec-all.h exec.c feature_to_c.sh fpu/softfloat-specialize.h fpu/softfloat.h fsdev/qemu-fsdev.h gdbstub.c gdbstub.h hw/acpi_piix4.c hw/arm_sysctl.c hw/cirrus_vga.c hw/file-op-9p.h hw/gt64xxx.c hw/hw.h hw/ide hw/lan9118.c hw/loader.c hw/lsi53c895a.c hw/m48t59.c hw/mainstone.c hw/mips.h hw/mips_malta.c hw/mips_timer.c hw/msi.c hw/msix.c hw/multiboot.c hw/pci.c hw/pci.h hw/piix4.c hw/piix_pci.c hw/pl031.c hw/pl050.c hw/pl080.c hw/pl110.c hw/pl190.c hw/ppc405_uc.c hw/pxa2xx.c hw/pxa2xx_lcd.c hw/qdev.c hw/qd ev.h hw/qxl.c hw/r2d.c hw/rtl8139.c hw/s390-virtio-bus.h hw/sh_pci.c hw/sh_pci.h hw/sh_serial.c hw/sm501.c hw/smc91c111.c hw/usb-bt.c hw/usb-bus.c hw/usb-desc.c hw/usb-desc.h hw/usb-hid.c hw/usb-hub.c hw/usb-msd.c hw/usb-musb.c hw/usb-net.c hw/usb-ohci.c hw/usb-serial.c hw/usb-uhci.c hw/usb-wacom.c hw/usb.c hw/usb.h hw/versatilepb.c hw/vga-pci.c hw/virtio-9p-xattr.h hw/virtio-9p.h hw/virtio-net.c hw/virtio-pci.c hw/virtio-serial-bus.c hw/virtio.c hw/virtio.h hw/vmware_vga.c hw/watchdog.h hw/zaurus.c hxtool kvm-all.c kvm-stub.c kvm.h linux-user/arm linux-user/ioctls.h linux-user/signal.c linux-user/syscall.c make_device_config.sh migration.c monitor.c pc-bios/keymaps pc-bios/optionrom qemu-binfmt-conf.sh qemu-common.h qemu-doc.texi qemu-io.c qemu-timer.c qerror.c qerror.h rules.mak savevm.c scripts/checkpatch.pl scripts/create_config scripts/feature_to_c.sh scripts/hxtool scripts/make_device_config.sh scripts/qemu-binfmt-conf.sh scripts/signrom.sh scripts/simpletrace.py scrip ts/texi2pod.pl scripts/tracetool simpletrace.py slirp/slirp.h slirp/tftp.c sysemu.h target-arm/cpu.h target-arm/helper.c target-arm/helpers.h target-arm/neon_helper.c target-arm/translate.c target-cris/translate.c target-i386/translate.c target-microblaze/helper.h target-microblaze/op_helper.c target-microblaze/translate.c target-mips/translate.c target-ppc/op_helper.c target-ppc/translate.c target-s390x/cpu.h target-sh4/cpu.h target-sh4/helper.c target-sh4/helper.h target-sh4/op_helper.c target-sh4/translate.c target-sparc/op_helper.c tcg/README tcg/arm tcg/ia64 tcg/mips tcg/tcg-op.h tcg/tcg-opc.h tests/Makefile tests/cris tests/hello-i386.c texi2pod.pl trace-events tracetool ui/cocoa.m ui/d3des.h ui/vnc-auth-sasl.c ui/x_keymap.h
Gerd Hoffmann
kraxel at kemper.freedesktop.org
Mon Jan 24 08:11:20 PST 2011
CODING_STYLE | 3
MAINTAINERS | 69
Makefile | 26
Makefile.objs | 2
Makefile.target | 10
arm-dis.c | 24
audio/alsaaudio.c | 2
audio/audio.c | 11
audio/audio_int.h | 2
audio/dsoundaudio.c | 4
audio/esdaudio.c | 3
audio/fmodaudio.c | 4
audio/mixeng.c | 25
audio/mixeng.h | 4
audio/mixeng_template.h | 39
audio/ossaudio.c | 3
audio/paaudio.c | 2
audio/spiceaudio.c | 5
audio/winwaveaudio.c | 3
block/vpc.c | 47
block/vvfat.c | 1
bsd-user/elfload.c | 37
cache-utils.h | 2
cmd.h | 36
configure | 466 +++---
create_config | 103 -
dis-asm.h | 87 -
disas.c | 5
docs/qdev-device-use.txt | 8
docs/specs/acpi_pci_hotplug.txt | 37
envlist.h | 14
exec-all.h | 2
exec.c | 7
feature_to_c.sh | 75 -
fpu/softfloat-specialize.h | 58
fpu/softfloat.h | 5
fsdev/qemu-fsdev.h | 4
gdbstub.c | 6
gdbstub.h | 2
hw/acpi_piix4.c | 39
hw/arm_sysctl.c | 17
hw/cirrus_vga.c | 1
hw/file-op-9p.h | 2
hw/gt64xxx.c | 120 -
hw/hw.h | 21
hw/ide/piix.c | 2
hw/lan9118.c | 4
hw/loader.c | 5
hw/lsi53c895a.c | 4
hw/m48t59.c | 11
hw/mainstone.c | 3
hw/mips.h | 4
hw/mips_malta.c | 4
hw/mips_timer.c | 44
hw/msi.c | 5
hw/msix.c | 5
hw/multiboot.c | 2
hw/pci.c | 37
hw/pci.h | 5
hw/piix4.c | 1
hw/piix_pci.c | 2
hw/pl031.c | 25
hw/pl050.c | 35
hw/pl080.c | 58
hw/pl110.c | 44
hw/pl190.c | 38
hw/ppc405_uc.c | 5
hw/pxa2xx.c | 2
hw/pxa2xx_lcd.c | 4
hw/qdev.c | 10
hw/qdev.h | 1
hw/qxl.c | 1
hw/r2d.c | 31
hw/rtl8139.c | 28
hw/s390-virtio-bus.h | 16
hw/sh_pci.c | 105 -
hw/sh_pci.h | 9
hw/sh_serial.c | 59
hw/sm501.c | 47
hw/smc91c111.c | 30
hw/usb-bt.c | 525 ++-----
hw/usb-bus.c | 129 +
hw/usb-desc.c | 406 +++++
hw/usb-desc.h | 92 +
hw/usb-hid.c | 491 ++----
hw/usb-hub.c | 250 +--
hw/usb-msd.c | 267 +--
hw/usb-musb.c | 44
hw/usb-net.c | 528 +++----
hw/usb-ohci.c | 88 -
hw/usb-serial.c | 236 +--
hw/usb-uhci.c | 98 -
hw/usb-wacom.c | 214 +-
hw/usb.c | 34
hw/usb.h | 50
hw/versatilepb.c | 24
hw/vga-pci.c | 1
hw/virtio-9p-xattr.h | 17
hw/virtio-9p.h | 4
hw/virtio-net.c | 28
hw/virtio-pci.c | 213 ++
hw/virtio-serial-bus.c | 10
hw/virtio.c | 36
hw/virtio.h | 4
hw/vmware_vga.c | 1
hw/watchdog.h | 8
hw/zaurus.c | 4
hxtool | 102 -
kvm-all.c | 49
kvm-stub.c | 5
kvm.h | 1
linux-user/arm/nwfpe/fpa11.h | 6
linux-user/arm/nwfpe/fpopcode.h | 4
linux-user/ioctls.h | 2
linux-user/signal.c | 16
linux-user/syscall.c | 4
make_device_config.sh | 28
migration.c | 4
monitor.c | 4
pc-bios/keymaps/bepo | 333 ++++
pc-bios/optionrom/Makefile | 2
pc-bios/optionrom/signrom.sh | 45
qemu-binfmt-conf.sh | 66
qemu-common.h | 2
qemu-doc.texi | 2
qemu-io.c | 4
qemu-timer.c | 15
qerror.c | 4
qerror.h | 3
rules.mak | 8
savevm.c | 40
scripts/checkpatch.pl | 2910 ++++++++++++++++++++++++++++++++++++++++
scripts/create_config | 103 +
scripts/feature_to_c.sh | 78 +
scripts/hxtool | 102 +
scripts/make_device_config.sh | 28
scripts/qemu-binfmt-conf.sh | 66
scripts/signrom.sh | 45
scripts/simpletrace.py | 93 +
scripts/texi2pod.pl | 477 ++++++
scripts/tracetool | 573 +++++++
simpletrace.py | 93 -
slirp/slirp.h | 2
slirp/tftp.c | 4
sysemu.h | 1
target-arm/cpu.h | 64
target-arm/helper.c | 29
target-arm/helpers.h | 4
target-arm/neon_helper.c | 47
target-arm/translate.c | 223 +--
target-cris/translate.c | 3
target-i386/translate.c | 34
target-microblaze/helper.h | 3
target-microblaze/op_helper.c | 45
target-microblaze/translate.c | 338 +++-
target-mips/translate.c | 8
target-ppc/op_helper.c | 192 +-
target-ppc/translate.c | 2
target-s390x/cpu.h | 6
target-sh4/cpu.h | 49
target-sh4/helper.c | 4
target-sh4/helper.h | 3
target-sh4/op_helper.c | 249 ++-
target-sh4/translate.c | 162 +-
target-sparc/op_helper.c | 56
tcg/README | 14
tcg/arm/tcg-target.c | 3
tcg/ia64/tcg-target.c | 3
tcg/mips/tcg-target.c | 4
tcg/tcg-op.h | 64
tcg/tcg-opc.h | 6
tests/Makefile | 3
tests/cris/check_abs.c | 5
tests/cris/check_addc.c | 3
tests/cris/check_addcm.c | 6
tests/cris/check_bound.c | 9
tests/cris/check_ftag.c | 12
tests/cris/check_int64.c | 6
tests/cris/check_lz.c | 2
tests/cris/check_swap.c | 2
tests/cris/crisutils.h | 20
tests/cris/sys.h | 4
tests/hello-i386.c | 4
texi2pod.pl | 477 ------
trace-events | 11
tracetool | 573 -------
ui/cocoa.m | 6
ui/d3des.h | 8
ui/vnc-auth-sasl.c | 14
ui/x_keymap.h | 4
190 files changed, 9535 insertions(+), 4504 deletions(-)
New commits:
commit 0bfe006c5380c5f8a485a55ded3329fbbc224396
Author: Kevin Wolf <mail at kevin-wolf.de>
Date: Tue Jan 4 14:03:30 2011 +0100
multiboot: Fix upper memory size in multiboot info
The upper memory size field should exclude the first MB of RAM.
Signed-off-by: Kevin Wolf <mail at kevin-wolf.de>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/multiboot.c b/hw/multiboot.c
index 7cc3055..0d2bfb4 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -306,7 +306,7 @@ int load_multiboot(void *fw_cfg,
| MULTIBOOT_FLAGS_MODULES
| MULTIBOOT_FLAGS_MMAP);
stl_p(bootinfo + MBI_MEM_LOWER, 640);
- stl_p(bootinfo + MBI_MEM_UPPER, ram_size / 1024);
+ stl_p(bootinfo + MBI_MEM_UPPER, (ram_size / 1024) - 1024);
stl_p(bootinfo + MBI_BOOT_DEVICE, 0x8001ffff); /* XXX: use the -boot switch? */
stl_p(bootinfo + MBI_MMAP_ADDR, ADDR_E820_MAP);
commit 64b85a8f2359ca3a995499afaf3c87d8e036e030
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sun Jan 23 16:21:20 2011 +0000
Delete useless 'extern' qualifiers for functions
'extern' qualifier is useless for function declarations. Delete
them.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/cache-utils.h b/cache-utils.h
index b45fde4..0b65907 100644
--- a/cache-utils.h
+++ b/cache-utils.h
@@ -9,7 +9,7 @@ struct qemu_cache_conf {
extern struct qemu_cache_conf qemu_cache_conf;
-extern void qemu_cache_utils_init(char **envp);
+void qemu_cache_utils_init(char **envp);
/* mildly adjusted code from tcg-dyngen.c */
static inline void flush_icache_range(unsigned long start, unsigned long stop)
diff --git a/cmd.h b/cmd.h
index cbe9549..b763b19 100644
--- a/cmd.h
+++ b/cmd.h
@@ -38,33 +38,33 @@ typedef struct cmdinfo {
extern cmdinfo_t *cmdtab;
extern int ncmds;
-extern void help_init(void);
-extern void quit_init(void);
+void help_init(void);
+void quit_init(void);
typedef int (*argsfunc_t)(int index);
typedef int (*checkfunc_t)(const cmdinfo_t *ci);
-extern void add_command(const cmdinfo_t *ci);
-extern void add_user_command(char *optarg);
-extern void add_args_command(argsfunc_t af);
-extern void add_check_command(checkfunc_t cf);
+void add_command(const cmdinfo_t *ci);
+void add_user_command(char *optarg);
+void add_args_command(argsfunc_t af);
+void add_check_command(checkfunc_t cf);
-extern const cmdinfo_t *find_command(const char *cmd);
+const cmdinfo_t *find_command(const char *cmd);
-extern void command_loop(void);
-extern int command_usage(const cmdinfo_t *ci);
-extern int command(const cmdinfo_t *ci, int argc, char **argv);
+void command_loop(void);
+int command_usage(const cmdinfo_t *ci);
+int command(const cmdinfo_t *ci, int argc, char **argv);
/* from input.h */
-extern char **breakline(char *input, int *count);
-extern void doneline(char *input, char **vec);
-extern char *fetchline(void);
+char **breakline(char *input, int *count);
+void doneline(char *input, char **vec);
+char *fetchline(void);
-extern long long cvtnum(char *s);
-extern void cvtstr(double value, char *str, size_t sz);
+long long cvtnum(char *s);
+void cvtstr(double value, char *str, size_t sz);
-extern struct timeval tsub(struct timeval t1, struct timeval t2);
-extern double tdiv(double value, struct timeval tv);
+struct timeval tsub(struct timeval t1, struct timeval t2);
+double tdiv(double value, struct timeval tv);
enum {
DEFAULT_TIME = 0x0,
@@ -72,7 +72,7 @@ enum {
VERBOSE_FIXED_TIME = 0x2
};
-extern void timestr(struct timeval *tv, char *str, size_t sz, int flags);
+void timestr(struct timeval *tv, char *str, size_t sz, int flags);
extern char *progname;
diff --git a/dis-asm.h b/dis-asm.h
index 356459c..296537a 100644
--- a/dis-asm.h
+++ b/dis-asm.h
@@ -362,48 +362,48 @@ typedef struct disassemble_info {
target address. Return number of bytes processed. */
typedef int (*disassembler_ftype) (bfd_vma, disassemble_info *);
-extern int print_insn_big_mips (bfd_vma, disassemble_info*);
-extern int print_insn_little_mips (bfd_vma, disassemble_info*);
-extern int print_insn_i386 (bfd_vma, disassemble_info*);
-extern int print_insn_m68k (bfd_vma, disassemble_info*);
-extern int print_insn_z8001 (bfd_vma, disassemble_info*);
-extern int print_insn_z8002 (bfd_vma, disassemble_info*);
-extern int print_insn_h8300 (bfd_vma, disassemble_info*);
-extern int print_insn_h8300h (bfd_vma, disassemble_info*);
-extern int print_insn_h8300s (bfd_vma, disassemble_info*);
-extern int print_insn_h8500 (bfd_vma, disassemble_info*);
-extern int print_insn_alpha (bfd_vma, disassemble_info*);
-extern disassembler_ftype arc_get_disassembler (int, int);
-extern int print_insn_arm (bfd_vma, disassemble_info*);
-extern int print_insn_sparc (bfd_vma, disassemble_info*);
-extern int print_insn_big_a29k (bfd_vma, disassemble_info*);
-extern int print_insn_little_a29k (bfd_vma, disassemble_info*);
-extern int print_insn_i960 (bfd_vma, disassemble_info*);
-extern int print_insn_sh (bfd_vma, disassemble_info*);
-extern int print_insn_shl (bfd_vma, disassemble_info*);
-extern int print_insn_hppa (bfd_vma, disassemble_info*);
-extern int print_insn_m32r (bfd_vma, disassemble_info*);
-extern int print_insn_m88k (bfd_vma, disassemble_info*);
-extern int print_insn_mn10200 (bfd_vma, disassemble_info*);
-extern int print_insn_mn10300 (bfd_vma, disassemble_info*);
-extern int print_insn_ns32k (bfd_vma, disassemble_info*);
-extern int print_insn_big_powerpc (bfd_vma, disassemble_info*);
-extern int print_insn_little_powerpc (bfd_vma, disassemble_info*);
-extern int print_insn_rs6000 (bfd_vma, disassemble_info*);
-extern int print_insn_w65 (bfd_vma, disassemble_info*);
-extern int print_insn_d10v (bfd_vma, disassemble_info*);
-extern int print_insn_v850 (bfd_vma, disassemble_info*);
-extern int print_insn_tic30 (bfd_vma, disassemble_info*);
-extern int print_insn_ppc (bfd_vma, disassemble_info*);
-extern int print_insn_s390 (bfd_vma, disassemble_info*);
-extern int print_insn_crisv32 (bfd_vma, disassemble_info*);
-extern int print_insn_crisv10 (bfd_vma, disassemble_info*);
-extern int print_insn_microblaze (bfd_vma, disassemble_info*);
-extern int print_insn_ia64 (bfd_vma, disassemble_info*);
+int print_insn_big_mips (bfd_vma, disassemble_info*);
+int print_insn_little_mips (bfd_vma, disassemble_info*);
+int print_insn_i386 (bfd_vma, disassemble_info*);
+int print_insn_m68k (bfd_vma, disassemble_info*);
+int print_insn_z8001 (bfd_vma, disassemble_info*);
+int print_insn_z8002 (bfd_vma, disassemble_info*);
+int print_insn_h8300 (bfd_vma, disassemble_info*);
+int print_insn_h8300h (bfd_vma, disassemble_info*);
+int print_insn_h8300s (bfd_vma, disassemble_info*);
+int print_insn_h8500 (bfd_vma, disassemble_info*);
+int print_insn_alpha (bfd_vma, disassemble_info*);
+disassembler_ftype arc_get_disassembler (int, int);
+int print_insn_arm (bfd_vma, disassemble_info*);
+int print_insn_sparc (bfd_vma, disassemble_info*);
+int print_insn_big_a29k (bfd_vma, disassemble_info*);
+int print_insn_little_a29k (bfd_vma, disassemble_info*);
+int print_insn_i960 (bfd_vma, disassemble_info*);
+int print_insn_sh (bfd_vma, disassemble_info*);
+int print_insn_shl (bfd_vma, disassemble_info*);
+int print_insn_hppa (bfd_vma, disassemble_info*);
+int print_insn_m32r (bfd_vma, disassemble_info*);
+int print_insn_m88k (bfd_vma, disassemble_info*);
+int print_insn_mn10200 (bfd_vma, disassemble_info*);
+int print_insn_mn10300 (bfd_vma, disassemble_info*);
+int print_insn_ns32k (bfd_vma, disassemble_info*);
+int print_insn_big_powerpc (bfd_vma, disassemble_info*);
+int print_insn_little_powerpc (bfd_vma, disassemble_info*);
+int print_insn_rs6000 (bfd_vma, disassemble_info*);
+int print_insn_w65 (bfd_vma, disassemble_info*);
+int print_insn_d10v (bfd_vma, disassemble_info*);
+int print_insn_v850 (bfd_vma, disassemble_info*);
+int print_insn_tic30 (bfd_vma, disassemble_info*);
+int print_insn_ppc (bfd_vma, disassemble_info*);
+int print_insn_s390 (bfd_vma, disassemble_info*);
+int print_insn_crisv32 (bfd_vma, disassemble_info*);
+int print_insn_crisv10 (bfd_vma, disassemble_info*);
+int print_insn_microblaze (bfd_vma, disassemble_info*);
+int print_insn_ia64 (bfd_vma, disassemble_info*);
#if 0
/* Fetch the disassembler for a given BFD, if that support is available. */
-extern disassembler_ftype disassembler (bfd *);
+disassembler_ftype disassembler(bfd *);
#endif
@@ -412,21 +412,20 @@ extern disassembler_ftype disassembler (bfd *);
/* Here is a function which callers may wish to use for read_memory_func.
It gets bytes from a buffer. */
-extern int buffer_read_memory
- (bfd_vma, bfd_byte *, int, struct disassemble_info *);
+int buffer_read_memory(bfd_vma, bfd_byte *, int, struct disassemble_info *);
/* This function goes with buffer_read_memory.
It prints a message using info->fprintf_func and info->stream. */
-extern void perror_memory (int, bfd_vma, struct disassemble_info *);
+void perror_memory(int, bfd_vma, struct disassemble_info *);
/* Just print the address in hex. This is included for completeness even
though both GDB and objdump provide their own (to print symbolic
addresses). */
-extern void generic_print_address (bfd_vma, struct disassemble_info *);
+void generic_print_address(bfd_vma, struct disassemble_info *);
/* Always true. */
-extern int generic_symbol_at_address (bfd_vma, struct disassemble_info *);
+int generic_symbol_at_address(bfd_vma, struct disassemble_info *);
/* Macro to initialize a disassemble_info struct. This should be called
by all applications creating such a struct. */
diff --git a/envlist.h b/envlist.h
index e76d4a1..b9addcc 100644
--- a/envlist.h
+++ b/envlist.h
@@ -7,13 +7,13 @@ extern "C" {
typedef struct envlist envlist_t;
-extern envlist_t *envlist_create(void);
-extern void envlist_free(envlist_t *);
-extern int envlist_setenv(envlist_t *, const char *);
-extern int envlist_unsetenv(envlist_t *, const char *);
-extern int envlist_parse_set(envlist_t *, const char *);
-extern int envlist_parse_unset(envlist_t *, const char *);
-extern char **envlist_to_environ(const envlist_t *, size_t *);
+envlist_t *envlist_create(void);
+void envlist_free(envlist_t *);
+int envlist_setenv(envlist_t *, const char *);
+int envlist_unsetenv(envlist_t *, const char *);
+int envlist_parse_set(envlist_t *, const char *);
+int envlist_parse_unset(envlist_t *, const char *);
+char **envlist_to_environ(const envlist_t *, size_t *);
#ifdef __cplusplus
}
diff --git a/exec-all.h b/exec-all.h
index a4b75bd..e3a82bc 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -192,7 +192,7 @@ extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
#if defined(USE_DIRECT_JUMP)
#if defined(_ARCH_PPC)
-extern void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr);
+void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr);
#define tb_set_jmp_target1 ppc_tb_set_jmp_target
#elif defined(__i386__) || defined(__x86_64__)
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
index 6c27881..a704043 100644
--- a/fsdev/qemu-fsdev.h
+++ b/fsdev/qemu-fsdev.h
@@ -49,7 +49,7 @@ typedef struct FsTypeListEntry {
QTAILQ_ENTRY(FsTypeListEntry) next;
} FsTypeListEntry;
-extern int qemu_fsdev_add(QemuOpts *opts);
-extern FsTypeEntry *get_fsdev_fsentry(char *id);
+int qemu_fsdev_add(QemuOpts *opts);
+FsTypeEntry *get_fsdev_fsentry(char *id);
extern FileOperations local_ops;
#endif
diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index c7731c2..126e60e 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -57,7 +57,7 @@ typedef struct FsContext
struct xattr_operations **xops;
} FsContext;
-extern void cred_init(FsCred *);
+void cred_init(FsCred *);
typedef struct FileOperations
{
diff --git a/hw/hw.h b/hw/hw.h
index 163a683..dd993de 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -799,17 +799,16 @@ extern const VMStateDescription vmstate_i2c_slave;
#define VMSTATE_END_OF_LIST() \
{}
-extern int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
- void *opaque, int version_id);
-extern void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
- void *opaque);
-extern int vmstate_register(DeviceState *dev, int instance_id,
- const VMStateDescription *vmsd, void *base);
-extern int vmstate_register_with_alias_id(DeviceState *dev,
- int instance_id,
- const VMStateDescription *vmsd,
- void *base, int alias_id,
- int required_for_version);
+int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
+ void *opaque, int version_id);
+void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
+ void *opaque);
+int vmstate_register(DeviceState *dev, int instance_id,
+ const VMStateDescription *vmsd, void *base);
+int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
+ const VMStateDescription *vmsd,
+ void *base, int alias_id,
+ int required_for_version);
void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
void *opaque);
#endif
diff --git a/hw/mips.h b/hw/mips.h
index 757e8f9..73aa8f8 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -21,7 +21,7 @@ int g364fb_mm_init(target_phys_addr_t vram_base,
void mipsnet_init(int base, qemu_irq irq, NICInfo *nd);
/* jazz_led.c */
-extern void jazz_led_init(target_phys_addr_t base);
+void jazz_led_init(target_phys_addr_t base);
/* rc4030.c */
typedef struct rc4030DMAState *rc4030_dma;
diff --git a/hw/s390-virtio-bus.h b/hw/s390-virtio-bus.h
index 669b610..33379a3 100644
--- a/hw/s390-virtio-bus.h
+++ b/hw/s390-virtio-bus.h
@@ -58,14 +58,12 @@ typedef struct VirtIOS390Bus {
} VirtIOS390Bus;
-extern void s390_virtio_device_update_status(VirtIOS390Device *dev);
+void s390_virtio_device_update_status(VirtIOS390Device *dev);
-extern VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus);
-extern VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size);
+VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus);
+VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size);
-extern VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
- ram_addr_t mem,
- int *vq_num);
-extern VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus,
- ram_addr_t mem);
-extern void s390_virtio_device_sync(VirtIOS390Device *dev);
+VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
+ ram_addr_t mem, int *vq_num);
+VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem);
+void s390_virtio_device_sync(VirtIOS390Device *dev);
diff --git a/hw/virtio-9p-xattr.h b/hw/virtio-9p-xattr.h
index a6e31a1..2bbae2d 100644
--- a/hw/virtio-9p-xattr.h
+++ b/hw/virtio-9p-xattr.h
@@ -41,16 +41,15 @@ extern XattrOperations *mapped_xattr_ops[];
extern XattrOperations *passthrough_xattr_ops[];
extern XattrOperations *none_xattr_ops[];
-extern ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
- const char *name, void *value, size_t size);
-extern ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
- void *value, size_t vsize);
-extern int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
+ssize_t v9fs_get_xattr(FsContext *ctx, const char *path, const char *name,
+ void *value, size_t size);
+ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, void *value,
+ size_t vsize);
+int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
void *value, size_t size, int flags);
-extern int v9fs_remove_xattr(FsContext *ctx,
- const char *path, const char *name);
-extern ssize_t pt_listxattr(FsContext *ctx, const char *path,
- char *name, void *value, size_t size);
+int v9fs_remove_xattr(FsContext *ctx, const char *path, const char *name);
+ssize_t pt_listxattr(FsContext *ctx, const char *path, char *name, void *value,
+ size_t size);
static inline ssize_t pt_getxattr(FsContext *ctx, const char *path,
const char *name, void *value, size_t size)
diff --git a/hw/virtio-9p.h b/hw/virtio-9p.h
index 6c23319..2ae4ce7 100644
--- a/hw/virtio-9p.h
+++ b/hw/virtio-9p.h
@@ -495,8 +495,8 @@ typedef struct V9fsReadLinkState
V9fsString target;
} V9fsReadLinkState;
-extern size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
- size_t offset, size_t size, int pack);
+size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
+ size_t offset, size_t size, int pack);
static inline size_t do_pdu_unpack(void *dst, struct iovec *sg, int sg_count,
size_t offset, size_t size)
diff --git a/hw/watchdog.h b/hw/watchdog.h
index 8fd32c3..c12a293 100644
--- a/hw/watchdog.h
+++ b/hw/watchdog.h
@@ -35,9 +35,9 @@ struct WatchdogTimerModel {
typedef struct WatchdogTimerModel WatchdogTimerModel;
/* in hw/watchdog.c */
-extern int select_watchdog(const char *p);
-extern int select_watchdog_action(const char *action);
-extern void watchdog_add_model(WatchdogTimerModel *model);
-extern void watchdog_perform_action(void);
+int select_watchdog(const char *p);
+int select_watchdog_action(const char *action);
+void watchdog_add_model(WatchdogTimerModel *model);
+void watchdog_perform_action(void);
#endif /* QEMU_WATCHDOG_H */
diff --git a/linux-user/arm/nwfpe/fpa11.h b/linux-user/arm/nwfpe/fpa11.h
index 07419e2..f17647b 100644
--- a/linux-user/arm/nwfpe/fpa11.h
+++ b/linux-user/arm/nwfpe/fpa11.h
@@ -89,9 +89,9 @@ typedef struct tagFPA11 {
extern FPA11* qemufpa;
-extern void resetFPA11(void);
-extern void SetRoundingMode(const unsigned int);
-extern void SetRoundingPrecision(const unsigned int);
+void resetFPA11(void);
+void SetRoundingMode(const unsigned int);
+void SetRoundingPrecision(const unsigned int);
static inline unsigned int readRegister(unsigned int reg)
{
diff --git a/linux-user/arm/nwfpe/fpopcode.h b/linux-user/arm/nwfpe/fpopcode.h
index 16fa34a..e7d1009 100644
--- a/linux-user/arm/nwfpe/fpopcode.h
+++ b/linux-user/arm/nwfpe/fpopcode.h
@@ -384,7 +384,7 @@ static inline float32 getSingleConstant(const unsigned int nIndex)
return float32Constant[nIndex];
}
-extern unsigned int getRegisterCount(const unsigned int opcode);
-extern unsigned int getDestinationSize(const unsigned int opcode);
+unsigned int getRegisterCount(const unsigned int opcode);
+unsigned int getDestinationSize(const unsigned int opcode);
#endif
diff --git a/qemu-common.h b/qemu-common.h
index 63d9943..c766b99 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -90,7 +90,7 @@ typedef int (*fprintf_function)(FILE *f, const char *fmt, ...)
#ifdef _WIN32
#define fsync _commit
#define lseek _lseeki64
-extern int qemu_ftruncate64(int, int64_t);
+int qemu_ftruncate64(int, int64_t);
#define ftruncate qemu_ftruncate64
static inline char *realpath(const char *path, char *resolved_path)
diff --git a/slirp/slirp.h b/slirp/slirp.h
index dfd977a..954289a 100644
--- a/slirp/slirp.h
+++ b/slirp/slirp.h
@@ -238,7 +238,7 @@ void if_start(struct ttys *);
#endif
#ifndef HAVE_STRERROR
- extern char *strerror(int error);
+ char *strerror(int error);
#endif
#ifndef HAVE_INDEX
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 8d73fad..e47c372 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -105,9 +105,9 @@ int cpu_s390x_handle_mmu_fault (CPUS390XState *env, target_ulong address, int rw
#define TARGET_VIRT_ADDR_SPACE_BITS 32
#ifndef CONFIG_USER_ONLY
-extern int s390_virtio_hypercall(CPUState *env);
-extern void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token);
-extern CPUState *s390_cpu_addr2state(uint16_t cpu_addr);
+int s390_virtio_hypercall(CPUState *env);
+void kvm_s390_virtio_irq(CPUState *env, int config_change, uint64_t token);
+CPUState *s390_cpu_addr2state(uint16_t cpu_addr);
#endif
diff --git a/tests/cris/sys.h b/tests/cris/sys.h
index d2ed4ce..c5f88e1 100644
--- a/tests/cris/sys.h
+++ b/tests/cris/sys.h
@@ -12,5 +12,5 @@
#define mb() asm volatile ("" : : : "memory")
-extern void pass(void);
-extern void _fail(char *reason);
+void pass(void);
+void _fail(char *reason);
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 56c789a..20f91bc 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -852,9 +852,9 @@ typedef struct CPSProcessSerNum
UInt32 hi;
} CPSProcessSerNum;
-extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
-extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
-extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
+OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
+OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
+OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
int main (int argc, const char * argv[]) {
diff --git a/ui/d3des.h b/ui/d3des.h
index ea3da44..78d546f 100644
--- a/ui/d3des.h
+++ b/ui/d3des.h
@@ -22,25 +22,25 @@
#define EN0 0 /* MODE == encrypt */
#define DE1 1 /* MODE == decrypt */
-extern void deskey(unsigned char *, int);
+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 *);
+void usekey(unsigned long *);
/* cookedkey[32]
* Loads the internal key register with the data in cookedkey.
*/
-extern void cpkey(unsigned long *);
+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 *);
+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'
diff --git a/ui/x_keymap.h b/ui/x_keymap.h
index 2042ce0..afde2e9 100644
--- a/ui/x_keymap.h
+++ b/ui/x_keymap.h
@@ -25,8 +25,8 @@
#ifndef QEMU_X_KEYMAP_H
#define QEMU_X_KEYMAP_H
-extern uint8_t translate_xfree86_keycode(const int key);
+uint8_t translate_xfree86_keycode(const int key);
-extern uint8_t translate_evdev_keycode(const int key);
+uint8_t translate_evdev_keycode(const int key);
#endif
commit ba76a84d2d420ccab7383bb60c61b96491f50b33
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sun Jan 23 11:43:25 2011 +0000
gdbstub-xml: avoid a warning from sparse
Include a header to get the declaration for xml_builtin. This
avoids a warning from sparse:
CC m68k-softmmu/gdbstub-xml.o
gdbstub-xml.c:244:12: warning: symbol 'xml_builtin' was not declared. Should it be static?
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/scripts/feature_to_c.sh b/scripts/feature_to_c.sh
index 0994d95..b62da8a 100644
--- a/scripts/feature_to_c.sh
+++ b/scripts/feature_to_c.sh
@@ -36,6 +36,9 @@ for input; do
arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'`
${AWK:-awk} 'BEGIN { n = 0
+ printf "#include \"config.h\"\n"
+ printf "#include \"qemu-common.h\"\n"
+ printf "#include \"gdbstub.h\"\n"
print "static const char '$arrayname'[] = {"
for (i = 0; i < 255; i++)
_ord_[sprintf("%c", i)] = i
commit 225d02cd1a34d5d87e8acefbf8e244a5d12f5f8c
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Sun Jan 23 04:44:51 2011 +0100
Avoid deadlock whith iothread and icount
When using the iothread together with icount, make sure the
qemu_icount counter makes forward progress when the vcpu is
idle to avoid deadlocks.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/qemu-timer.c b/qemu-timer.c
index 95814af..db1ec49 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -110,7 +110,6 @@ static int64_t cpu_get_clock(void)
}
}
-#ifndef CONFIG_IOTHREAD
static int64_t qemu_icount_delta(void)
{
if (!use_icount) {
@@ -124,7 +123,6 @@ static int64_t qemu_icount_delta(void)
return cpu_get_icount() - cpu_get_clock();
}
}
-#endif
/* enable cpu_get_ticks() */
void cpu_enable_ticks(void)
@@ -1077,9 +1075,17 @@ void quit_timers(void)
int qemu_calculate_timeout(void)
{
-#ifndef CONFIG_IOTHREAD
int timeout;
+#ifdef CONFIG_IOTHREAD
+ /* When using icount, making forward progress with qemu_icount when the
+ guest CPU is idle is critical. We only use the static io-thread timeout
+ for non icount runs. */
+ if (!use_icount) {
+ return 1000;
+ }
+#endif
+
if (!vm_running)
timeout = 5000;
else {
@@ -1110,8 +1116,5 @@ int qemu_calculate_timeout(void)
}
return timeout;
-#else /* CONFIG_IOTHREAD */
- return 1000;
-#endif
}
commit 5d0bb8239d84292380d0024acd0d510cc957dae0
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Sun Jan 23 03:52:20 2011 +0100
microblaze: cleanup helper_addkc
Remove unused addition and rename to helper_carry.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index 9c2a1e4..1696b88 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -2,7 +2,7 @@
DEF_HELPER_1(raise_exception, void, i32)
DEF_HELPER_0(debug, void)
-DEF_HELPER_FLAGS_3(addkc, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_3(carry, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
DEF_HELPER_2(cmp, i32, i32, i32)
DEF_HELPER_2(cmpu, i32, i32, i32)
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 59e4674..d75a53c 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -128,12 +128,9 @@ uint32_t helper_cmpu(uint32_t a, uint32_t b)
return t;
}
-uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t cf)
+uint32_t helper_carry(uint32_t a, uint32_t b, uint32_t cf)
{
- uint32_t d, ncf;
-
- d = a + b + cf;
-
+ uint32_t ncf;
ncf = compute_carry(a, b, cf);
return ncf;
}
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 0c5edc3..2207431 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -232,13 +232,13 @@ static void dec_add(DisasContext *dc)
if (dc->rd) {
TCGv ncf = tcg_temp_new();
- gen_helper_addkc(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
+ gen_helper_carry(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
write_carry(dc, ncf);
tcg_temp_free(ncf);
} else {
- gen_helper_addkc(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
+ gen_helper_carry(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
write_carry(dc, cf);
}
tcg_temp_free(cf);
@@ -302,13 +302,13 @@ static void dec_sub(DisasContext *dc)
if (dc->rd) {
TCGv ncf = tcg_temp_new();
- gen_helper_addkc(ncf, na, *(dec_alu_op_b(dc)), cf);
+ gen_helper_carry(ncf, na, *(dec_alu_op_b(dc)), cf);
tcg_gen_add_tl(cpu_R[dc->rd], na, *(dec_alu_op_b(dc)));
tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
write_carry(dc, ncf);
tcg_temp_free(ncf);
} else {
- gen_helper_addkc(cf, na, *(dec_alu_op_b(dc)), cf);
+ gen_helper_carry(cf, na, *(dec_alu_op_b(dc)), cf);
write_carry(dc, cf);
}
tcg_temp_free(cf);
commit e0a42ebc0831e3ae18e965cc202b5d6649cc38f2
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Sat Jan 22 12:39:16 2011 +0100
microblaze: Improve subkc
Move code from the helper into the translator. The remaining
helper parts can reuse helper_addkc, making it possible to
remove helper_subkc entirely.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index 4871406..9c2a1e4 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -3,7 +3,6 @@
DEF_HELPER_1(raise_exception, void, i32)
DEF_HELPER_0(debug, void)
DEF_HELPER_FLAGS_3(addkc, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
-DEF_HELPER_4(subkc, i32, i32, i32, i32, i32)
DEF_HELPER_2(cmp, i32, i32, i32)
DEF_HELPER_2(cmpu, i32, i32, i32)
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index eb5a8b7..59e4674 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -138,28 +138,6 @@ uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t cf)
return ncf;
}
-uint32_t helper_subkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
-{
- uint32_t d, cf = 1, ncf;
-
- if (c)
- cf = env->sregs[SR_MSR] >> 31;
- assert(cf == 0 || cf == 1);
- d = b + ~a + cf;
-
- if (!k) {
- ncf = compute_carry(b, ~a, cf);
- assert(ncf == 0 || ncf == 1);
- if (ncf)
- env->sregs[SR_MSR] |= MSR_C | MSR_CC;
- else
- env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
- }
- D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
- d, a, b, cf, ncf, k, c));
- return d;
-}
-
static inline int div_prepare(uint32_t a, uint32_t b)
{
if (b == 0) {
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 264395b..0c5edc3 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -247,6 +247,7 @@ static void dec_add(DisasContext *dc)
static void dec_sub(DisasContext *dc)
{
unsigned int u, cmp, k, c;
+ TCGv cf, na;
u = dc->imm & 2;
k = dc->opcode & 4;
@@ -261,24 +262,57 @@ static void dec_sub(DisasContext *dc)
else
gen_helper_cmp(cpu_R[dc->rd], cpu_R[dc->ra], cpu_R[dc->rb]);
}
- } else {
- LOG_DIS("sub%s%s r%d, r%d r%d\n",
- k ? "k" : "", c ? "c" : "", dc->rd, dc->ra, dc->rb);
+ return;
+ }
- if (!k || c) {
- TCGv t;
- t = tcg_temp_new();
- if (dc->rd)
- gen_helper_subkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
- tcg_const_tl(k), tcg_const_tl(c));
- else
- gen_helper_subkc(t, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
- tcg_const_tl(k), tcg_const_tl(c));
- tcg_temp_free(t);
- }
- else if (dc->rd)
+ LOG_DIS("sub%s%s r%d, r%d r%d\n",
+ k ? "k" : "", c ? "c" : "", dc->rd, dc->ra, dc->rb);
+
+ /* Take care of the easy cases first. */
+ if (k) {
+ /* k - keep carry, no need to update MSR. */
+ /* If rd == r0, it's a nop. */
+ if (dc->rd) {
tcg_gen_sub_tl(cpu_R[dc->rd], *(dec_alu_op_b(dc)), cpu_R[dc->ra]);
+
+ if (c) {
+ /* c - Add carry into the result. */
+ cf = tcg_temp_new();
+
+ read_carry(dc, cf);
+ tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
+ tcg_temp_free(cf);
+ }
+ }
+ return;
+ }
+
+ /* From now on, we can assume k is zero. So we need to update MSR. */
+ /* Extract carry. And complement a into na. */
+ cf = tcg_temp_new();
+ na = tcg_temp_new();
+ if (c) {
+ read_carry(dc, cf);
+ } else {
+ tcg_gen_movi_tl(cf, 1);
+ }
+
+ /* d = b + ~a + c. carry defaults to 1. */
+ tcg_gen_not_tl(na, cpu_R[dc->ra]);
+
+ if (dc->rd) {
+ TCGv ncf = tcg_temp_new();
+ gen_helper_addkc(ncf, na, *(dec_alu_op_b(dc)), cf);
+ tcg_gen_add_tl(cpu_R[dc->rd], na, *(dec_alu_op_b(dc)));
+ tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
+ write_carry(dc, ncf);
+ tcg_temp_free(ncf);
+ } else {
+ gen_helper_addkc(cf, na, *(dec_alu_op_b(dc)), cf);
+ write_carry(dc, cf);
}
+ tcg_temp_free(cf);
+ tcg_temp_free(na);
}
static void dec_pattern(DisasContext *dc)
commit 7e9e4330080f40a964cfed2b334b5e231e967792
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Sat Jan 22 12:35:48 2011 +0100
microblaze: Fix 3rd addkc arg when rd is r0
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index d983c8b..264395b 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -238,8 +238,7 @@ static void dec_add(DisasContext *dc)
write_carry(dc, ncf);
tcg_temp_free(ncf);
} else {
- gen_helper_addkc(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
- tcg_const_tl(cf));
+ gen_helper_addkc(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
write_carry(dc, cf);
}
tcg_temp_free(cf);
commit 40cbf5b7098981f66ef161e6ce7a9f6770537ea4
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Sat Jan 22 12:02:53 2011 +0100
microblaze: Improve addkc
* Optimize handling when carry is not updated.
* Optimize handling for adds with nop semantics.
* Move code from helper_addkc to the translator making
helper_addkc PURE and CONST.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/target-microblaze/helper.h b/target-microblaze/helper.h
index 11ad1b6..4871406 100644
--- a/target-microblaze/helper.h
+++ b/target-microblaze/helper.h
@@ -2,7 +2,7 @@
DEF_HELPER_1(raise_exception, void, i32)
DEF_HELPER_0(debug, void)
-DEF_HELPER_4(addkc, i32, i32, i32, i32, i32)
+DEF_HELPER_FLAGS_3(addkc, TCG_CALL_PURE | TCG_CALL_CONST, i32, i32, i32, i32)
DEF_HELPER_4(subkc, i32, i32, i32, i32, i32)
DEF_HELPER_2(cmp, i32, i32, i32)
DEF_HELPER_2(cmpu, i32, i32, i32)
diff --git a/target-microblaze/op_helper.c b/target-microblaze/op_helper.c
index 97461ae..eb5a8b7 100644
--- a/target-microblaze/op_helper.c
+++ b/target-microblaze/op_helper.c
@@ -128,26 +128,14 @@ uint32_t helper_cmpu(uint32_t a, uint32_t b)
return t;
}
-uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
+uint32_t helper_addkc(uint32_t a, uint32_t b, uint32_t cf)
{
- uint32_t d, cf = 0, ncf;
+ uint32_t d, ncf;
- if (c)
- cf = env->sregs[SR_MSR] >> 31;
- assert(cf == 0 || cf == 1);
d = a + b + cf;
- if (!k) {
- ncf = compute_carry(a, b, cf);
- assert(ncf == 0 || ncf == 1);
- if (ncf)
- env->sregs[SR_MSR] |= MSR_C | MSR_CC;
- else
- env->sregs[SR_MSR] &= ~(MSR_C | MSR_CC);
- }
- D(qemu_log("%x = %x + %x cf=%d ncf=%d k=%d c=%d\n",
- d, a, b, cf, ncf, k, c));
- return d;
+ ncf = compute_carry(a, b, cf);
+ return ncf;
}
uint32_t helper_subkc(uint32_t a, uint32_t b, uint32_t k, uint32_t c)
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index dd2865c..d983c8b 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -193,6 +193,7 @@ static inline TCGv *dec_alu_op_b(DisasContext *dc)
static void dec_add(DisasContext *dc)
{
unsigned int k, c;
+ TCGv cf;
k = dc->opcode & 4;
c = dc->opcode & 2;
@@ -201,17 +202,47 @@ static void dec_add(DisasContext *dc)
dc->type_b ? "i" : "", k ? "k" : "", c ? "c" : "",
dc->rd, dc->ra, dc->rb);
- if (k && !c && dc->rd)
+ /* Take care of the easy cases first. */
+ if (k) {
+ /* k - keep carry, no need to update MSR. */
+ /* If rd == r0, it's a nop. */
+ if (dc->rd) {
+ tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
+
+ if (c) {
+ /* c - Add carry into the result. */
+ cf = tcg_temp_new();
+
+ read_carry(dc, cf);
+ tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
+ tcg_temp_free(cf);
+ }
+ }
+ return;
+ }
+
+ /* From now on, we can assume k is zero. So we need to update MSR. */
+ /* Extract carry. */
+ cf = tcg_temp_new();
+ if (c) {
+ read_carry(dc, cf);
+ } else {
+ tcg_gen_movi_tl(cf, 0);
+ }
+
+ if (dc->rd) {
+ TCGv ncf = tcg_temp_new();
+ gen_helper_addkc(ncf, cpu_R[dc->ra], *(dec_alu_op_b(dc)), cf);
tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
- else if (dc->rd)
- gen_helper_addkc(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)),
- tcg_const_tl(k), tcg_const_tl(c));
- else {
- TCGv d = tcg_temp_new();
- gen_helper_addkc(d, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
- tcg_const_tl(k), tcg_const_tl(c));
- tcg_temp_free(d);
+ tcg_gen_add_tl(cpu_R[dc->rd], cpu_R[dc->rd], cf);
+ write_carry(dc, ncf);
+ tcg_temp_free(ncf);
+ } else {
+ gen_helper_addkc(cf, cpu_R[dc->ra], *(dec_alu_op_b(dc)),
+ tcg_const_tl(cf));
+ write_carry(dc, cf);
}
+ tcg_temp_free(cf);
}
static void dec_sub(DisasContext *dc)
commit 2accfb5fa6f097845915973a06824bc72fb26e94
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Sat Jan 22 12:00:12 2011 +0100
microblaze: Remove debug leftovers.
No functional changes.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index dcc867e..dd2865c 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -884,7 +884,6 @@ static void dec_load(DisasContext *dc)
tcg_gen_sub_tl(low, tcg_const_tl(3), low);
tcg_gen_andi_tl(t, t, ~3);
tcg_gen_or_tl(t, t, low);
- tcg_gen_mov_tl(env_debug, low);
tcg_gen_mov_tl(env_imm, t);
tcg_temp_free(low);
break;
@@ -1010,7 +1009,6 @@ static void dec_store(DisasContext *dc)
tcg_gen_sub_tl(low, tcg_const_tl(3), low);
tcg_gen_andi_tl(t, t, ~3);
tcg_gen_or_tl(t, t, low);
- tcg_gen_mov_tl(env_debug, low);
tcg_gen_mov_tl(env_imm, t);
tcg_temp_free(low);
break;
commit ee8b246f825efa0aa299fc33b8dcc8a8a862cc53
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Sat Jan 22 11:57:19 2011 +0100
microblaze: Reorganize for future patches
No functional changes.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 4b6ae06..dcc867e 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -153,6 +153,23 @@ static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
}
}
+static void read_carry(DisasContext *dc, TCGv d)
+{
+ tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31);
+}
+
+static void write_carry(DisasContext *dc, TCGv v)
+{
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_shli_tl(t0, v, 31);
+ tcg_gen_sari_tl(t0, t0, 31);
+ tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC));
+ tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR],
+ ~(MSR_C | MSR_CC));
+ tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0);
+ tcg_temp_free(t0);
+}
+
/* True if ALU operand b is a small immediate that may deserve
faster treatment. */
static inline int dec_alu_op_b_is_small_imm(DisasContext *dc)
@@ -337,25 +354,6 @@ static void dec_xor(DisasContext *dc)
tcg_gen_xor_tl(cpu_R[dc->rd], cpu_R[dc->ra], *(dec_alu_op_b(dc)));
}
-static void read_carry(DisasContext *dc, TCGv d)
-{
- tcg_gen_shri_tl(d, cpu_SR[SR_MSR], 31);
-}
-
-static void write_carry(DisasContext *dc, TCGv v)
-{
- TCGv t0 = tcg_temp_new();
- tcg_gen_shli_tl(t0, v, 31);
- tcg_gen_sari_tl(t0, t0, 31);
- tcg_gen_mov_tl(env_debug, t0);
- tcg_gen_andi_tl(t0, t0, (MSR_C | MSR_CC));
- tcg_gen_andi_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR],
- ~(MSR_C | MSR_CC));
- tcg_gen_or_tl(cpu_SR[SR_MSR], cpu_SR[SR_MSR], t0);
- tcg_temp_free(t0);
-}
-
-
static inline void msr_read(DisasContext *dc, TCGv d)
{
tcg_gen_mov_tl(d, cpu_SR[SR_MSR]);
commit 5823947f9f1e55fb6599c9ed769ce25cdec38355
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Fri Jan 21 23:12:42 2011 +0100
ppc: Correct BookE tlb reads
Call the tlb read helper (and not the write helper) for tlb
reads.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 74e06d7..89413c5 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -5874,7 +5874,7 @@ static void gen_tlbre_440(DisasContext *ctx)
case 2:
{
TCGv_i32 t0 = tcg_const_i32(rB(ctx->opcode));
- gen_helper_440_tlbwe(t0, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
+ gen_helper_440_tlbre(cpu_gpr[rD(ctx->opcode)], t0, cpu_gpr[rA(ctx->opcode)]);
tcg_temp_free_i32(t0);
}
break;
commit 789f88d0b21fedfd4251d56bb7a9fbfbda7a4ac7
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 18:19:40 2011 +0100
checkpatch: Fix bracing false positives on #else
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 55ef439..4fa06c0 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -2536,7 +2536,8 @@ sub process {
}
}
if (!defined $suppress_ifbraces{$linenr - 1} &&
- $line =~ /\b(if|while|for|else)\b/) {
+ $line =~ /\b(if|while|for|else)\b/ &&
+ $line !~ /\#\s*else/) {
my $allowed = 0;
# Check the pre-context.
commit b947c12c0bb217fe09968e652873e0d22b269d68
Merge: 543c4c9... ace1318...
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 21 17:56:50 2011 +0100
Merge branch 'usb.4' of git://anongit.freedesktop.org/spice/qemu
* 'usb.4' of git://anongit.freedesktop.org/spice/qemu: (32 commits)
usb: zap pdev from usbport
usb: rewrite fw path, fix numbering
usb: add port property.
usb: keep track of physical port address.
usb storage: handle long responses
usb storage: fix status reporting
usb storage: high speed support
usb: add device qualifier support
usb: add usb_desc_attach
usb: add attach callback
usb: add speed mask to ports
usb: hid: change serial number to "42".
usb: hid: remote wakeup support.
usb: hub: remote wakeup support.
usb: uhci: remote wakeup support.
usb: add usb_wakeup() + wakeup callback to port ops
usb: rework attach/detach workflow
usb: create USBPortOps, move attach there.
usb: move remote wakeup handling to common code
usb: move USB_REQ_{GET,SET}_CONFIGURATION handling to common code
...
commit 543c4c94cf235d11315157bab25a24f7d9a48711
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 21 17:56:32 2011 +0100
sm501: fix screen redraw
Due to signed/unsigned comparison, the dirty bits are never reset, and
the screen redrawn each time. Fix that by only using ram_addr_t types,
and looking for page_min != addr_max instead.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/sm501.c b/hw/sm501.c
index 388fc08..0f0bf96 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -1274,8 +1274,8 @@ static void sm501_draw_crt(SM501State * s)
draw_hwc_line_func * draw_hwc_line = NULL;
int full_update = 0;
int y_start = -1;
- int page_min = 0x7fffffff;
- int page_max = -1;
+ ram_addr_t page_min = ~0l;
+ ram_addr_t page_max = 0l;
ram_addr_t offset = s->local_mem_offset;
/* choose draw_line function */
@@ -1371,9 +1371,10 @@ static void sm501_draw_crt(SM501State * s)
dpy_update(s->ds, 0, y_start, width, y - y_start);
/* clear dirty flags */
- if (page_max != -1)
+ if (page_min != ~0l) {
cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
VGA_DIRTY_FLAG);
+ }
}
static void sm501_update_display(void *opaque)
commit b646968336d4180bdd7d2e24209708dcee6ba400
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Thu Jan 20 20:58:56 2011 +0000
checkpatch: adjust to QEMUisms
Change checkpatch.pl for QEMU use:
- Root directory detection
- Forbid tabs
- Indent at 4 spaces
- Allow typedefs
- Enforce brace use even for single statement blocks
- Don't suggest nonexistent cleanup tools
Mention the script in CODING_STYLE.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/CODING_STYLE b/CODING_STYLE
index 2c8268d..5ecfa22 100644
--- a/CODING_STYLE
+++ b/CODING_STYLE
@@ -1,6 +1,9 @@
Qemu Coding Style
=================
+Please use the script checkpatch.pl in the scripts directory to check
+patches before submitting.
+
1. Whitespace
Of course, the most important aspect in any coding style is whitespace.
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
old mode 100644
new mode 100755
index 2a8a0e2..55ef439
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -328,9 +328,9 @@ sub top_of_kernel_tree {
my ($root) = @_;
my @tree_check = (
- "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile",
- "README", "Documentation", "arch", "include", "drivers",
- "fs", "init", "ipc", "kernel", "lib", "scripts",
+ "COPYING", "MAINTAINERS", "Makefile",
+ "README", "docs", "VERSION",
+ "vl.c"
);
foreach my $check (@tree_check) {
@@ -1494,31 +1494,13 @@ sub process {
# check we are in a valid source file C or perl if not then ignore this hunk
next if ($realfile !~ /\.(h|c|pl)$/);
-# at the beginning of a line any tabs must come first and anything
-# more than 8 must use tabs.
- if ($rawline =~ /^\+\s* \t\s*\S/ ||
- $rawline =~ /^\+\s* \s*/) {
+# in QEMU, no tabs are allowed
+ if ($rawline =~ /\t/) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
- ERROR("code indent should use tabs where possible\n" . $herevet);
+ ERROR("code indent should never use tabs\n" . $herevet);
$rpt_cleaners = 1;
}
-# check for space before tabs.
- if ($rawline =~ /^\+/ && $rawline =~ / \t/) {
- my $herevet = "$here\n" . cat_vet($rawline) . "\n";
- WARN("please, no space before tabs\n" . $herevet);
- }
-
-# check for spaces at the beginning of a line.
-# Exceptions:
-# 1) within comments
-# 2) indented preprocessor commands
-# 3) hanging labels
- if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/) {
- my $herevet = "$here\n" . cat_vet($rawline) . "\n";
- WARN("please, no spaces at the start of a line\n" . $herevet);
- }
-
# check we are in a valid C source file if not then ignore this hunk
next if ($realfile !~ /\.(h|c)$/);
@@ -1746,7 +1728,7 @@ sub process {
#print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n";
- if ($check && (($sindent % 8) != 0 ||
+ if ($check && (($sindent % 4) != 0 ||
($sindent <= $indent && $s ne ''))) {
WARN("suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
}
@@ -1869,16 +1851,6 @@ sub process {
$herecurr);
}
-# check for new typedefs, only function parameters and sparse annotations
-# make sense.
- if ($line =~ /\btypedef\s/ &&
- $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ &&
- $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ &&
- $line !~ /\b$typeTypedefs\b/ &&
- $line !~ /\b__bitwise(?:__|)\b/) {
- WARN("do not add new typedefs\n" . $herecurr);
- }
-
# * goes on variable not on type
# (char*[ const])
if ($line =~ m{\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\)}) {
@@ -2514,13 +2486,13 @@ sub process {
WARN("vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr);
}
-# check for redundant bracing round if etc
- if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) {
+# check for missing bracing round if etc
+ if ($line =~ /(^.*)\bif\b/ && $line !~ /\#\s*if/) {
my ($level, $endln, @chunks) =
ctx_statement_full($linenr, $realcnt, 1);
#print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
#print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";
- if ($#chunks > 0 && $level == 0) {
+ if ($#chunks >= 0 && $level == 0) {
my $allowed = 0;
my $seen = 0;
my $herectx = $here . "\n";
@@ -2558,8 +2530,8 @@ sub process {
$allowed = 1;
}
}
- if ($seen && !$allowed) {
- WARN("braces {} are not necessary for any arm of this statement\n" . $herectx);
+ if (!$seen) {
+ WARN("braces {} are necessary for all arms of this statement\n" . $herectx);
}
}
}
@@ -2605,7 +2577,7 @@ sub process {
$allowed = 1;
}
}
- if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {
+ if ($level == 0 && $block !~ /^\s*\{/ && !$allowed) {
my $herectx = $here . "\n";;
my $cnt = statement_rawlines($block);
@@ -2613,7 +2585,7 @@ sub process {
$herectx .= raw_line($linenr, $n) . "\n";;
}
- WARN("braces {} are not necessary for single statement blocks\n" . $herectx);
+ WARN("braces {} are necessary even for single statement blocks\n" . $herectx);
}
}
@@ -2918,10 +2890,10 @@ sub process {
if ($quiet == 0) {
# If there were whitespace errors which cleanpatch can fix
# then suggest that.
- if ($rpt_cleaners) {
- print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
- print " scripts/cleanfile\n\n";
- }
+# if ($rpt_cleaners) {
+# print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
+# print " scripts/cleanfile\n\n";
+# }
}
if ($clean == 1 && $quiet == 0) {
commit 1ec3f6f9abca4f4f73d7e8a74dd9b14c1f087a8e
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Thu Jan 20 20:54:26 2011 +0000
Add checkpatch.pl from Linux kernel
Unchanged import from
http://www.kernel.org/pub/linux/kernel/people/apw/checkpatch/checkpatch.pl-0.31
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
new file mode 100644
index 0000000..2a8a0e2
--- /dev/null
+++ b/scripts/checkpatch.pl
@@ -0,0 +1,2937 @@
+#!/usr/bin/perl -w
+# (c) 2001, Dave Jones. (the file handling bit)
+# (c) 2005, Joel Schopp <jschopp at austin.ibm.com> (the ugly bit)
+# (c) 2007,2008, Andy Whitcroft <apw at uk.ibm.com> (new conditions, test suite)
+# (c) 2008-2010 Andy Whitcroft <apw at canonical.com>
+# Licensed under the terms of the GNU GPL License version 2
+
+use strict;
+
+my $P = $0;
+$P =~ s at .*/@@g;
+
+my $V = '0.31';
+
+use Getopt::Long qw(:config no_auto_abbrev);
+
+my $quiet = 0;
+my $tree = 1;
+my $chk_signoff = 1;
+my $chk_patch = 1;
+my $tst_only;
+my $emacs = 0;
+my $terse = 0;
+my $file = 0;
+my $check = 0;
+my $summary = 1;
+my $mailback = 0;
+my $summary_file = 0;
+my $root;
+my %debug;
+my $help = 0;
+
+sub help {
+ my ($exitcode) = @_;
+
+ print << "EOM";
+Usage: $P [OPTION]... [FILE]...
+Version: $V
+
+Options:
+ -q, --quiet quiet
+ --no-tree run without a kernel tree
+ --no-signoff do not check for 'Signed-off-by' line
+ --patch treat FILE as patchfile (default)
+ --emacs emacs compile window format
+ --terse one line per report
+ -f, --file treat FILE as regular source file
+ --subjective, --strict enable more subjective tests
+ --root=PATH PATH to the kernel tree root
+ --no-summary suppress the per-file summary
+ --mailback only produce a report in case of warnings/errors
+ --summary-file include the filename in summary
+ --debug KEY=[0|1] turn on/off debugging of KEY, where KEY is one of
+ 'values', 'possible', 'type', and 'attr' (default
+ is all off)
+ --test-only=WORD report only warnings/errors containing WORD
+ literally
+ -h, --help, --version display this help and exit
+
+When FILE is - read standard input.
+EOM
+
+ exit($exitcode);
+}
+
+GetOptions(
+ 'q|quiet+' => \$quiet,
+ 'tree!' => \$tree,
+ 'signoff!' => \$chk_signoff,
+ 'patch!' => \$chk_patch,
+ 'emacs!' => \$emacs,
+ 'terse!' => \$terse,
+ 'f|file!' => \$file,
+ 'subjective!' => \$check,
+ 'strict!' => \$check,
+ 'root=s' => \$root,
+ 'summary!' => \$summary,
+ 'mailback!' => \$mailback,
+ 'summary-file!' => \$summary_file,
+
+ 'debug=s' => \%debug,
+ 'test-only=s' => \$tst_only,
+ 'h|help' => \$help,
+ 'version' => \$help
+) or help(1);
+
+help(0) if ($help);
+
+my $exit = 0;
+
+if ($#ARGV < 0) {
+ print "$P: no input files\n";
+ exit(1);
+}
+
+my $dbg_values = 0;
+my $dbg_possible = 0;
+my $dbg_type = 0;
+my $dbg_attr = 0;
+for my $key (keys %debug) {
+ ## no critic
+ eval "\${dbg_$key} = '$debug{$key}';";
+ die "$@" if ($@);
+}
+
+my $rpt_cleaners = 0;
+
+if ($terse) {
+ $emacs = 1;
+ $quiet++;
+}
+
+if ($tree) {
+ if (defined $root) {
+ if (!top_of_kernel_tree($root)) {
+ die "$P: $root: --root does not point at a valid tree\n";
+ }
+ } else {
+ if (top_of_kernel_tree('.')) {
+ $root = '.';
+ } elsif ($0 =~ m@(.*)/scripts/[^/]*$@ &&
+ top_of_kernel_tree($1)) {
+ $root = $1;
+ }
+ }
+
+ if (!defined $root) {
+ print "Must be run from the top-level dir. of a kernel tree\n";
+ exit(2);
+ }
+}
+
+my $emitted_corrupt = 0;
+
+our $Ident = qr{
+ [A-Za-z_][A-Za-z\d_]*
+ (?:\s*\#\#\s*[A-Za-z_][A-Za-z\d_]*)*
+ }x;
+our $Storage = qr{extern|static|asmlinkage};
+our $Sparse = qr{
+ __user|
+ __kernel|
+ __force|
+ __iomem|
+ __must_check|
+ __init_refok|
+ __kprobes|
+ __ref
+ }x;
+
+# Notes to $Attribute:
+# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
+our $Attribute = qr{
+ const|
+ __percpu|
+ __nocast|
+ __safe|
+ __bitwise__|
+ __packed__|
+ __packed2__|
+ __naked|
+ __maybe_unused|
+ __always_unused|
+ __noreturn|
+ __used|
+ __cold|
+ __noclone|
+ __deprecated|
+ __read_mostly|
+ __kprobes|
+ __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)|
+ ____cacheline_aligned|
+ ____cacheline_aligned_in_smp|
+ ____cacheline_internodealigned_in_smp|
+ __weak
+ }x;
+our $Modifier;
+our $Inline = qr{inline|__always_inline|noinline};
+our $Member = qr{->$Ident|\.$Ident|\[[^]]*\]};
+our $Lval = qr{$Ident(?:$Member)*};
+
+our $Constant = qr{(?:[0-9]+|0x[0-9a-fA-F]+)[UL]*};
+our $Assignment = qr{(?:\*\=|/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|=|=)};
+our $Compare = qr{<=|>=|==|!=|<|>};
+our $Operators = qr{
+ <=|>=|==|!=|
+ =>|->|<<|>>|<|>|!|~|
+ &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%
+ }x;
+
+our $NonptrType;
+our $Type;
+our $Declare;
+
+our $UTF8 = qr {
+ [\x09\x0A\x0D\x20-\x7E] # ASCII
+ | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
+ | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
+ | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
+ | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
+ | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
+ | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
+ | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
+}x;
+
+our $typeTypedefs = qr{(?x:
+ (?:__)?(?:u|s|be|le)(?:8|16|32|64)|
+ atomic_t
+)};
+
+our $logFunctions = qr{(?x:
+ printk|
+ pr_(debug|dbg|vdbg|devel|info|warning|err|notice|alert|crit|emerg|cont)|
+ (dev|netdev|netif)_(printk|dbg|vdbg|info|warn|err|notice|alert|crit|emerg|WARN)|
+ WARN|
+ panic
+)};
+
+our @typeList = (
+ qr{void},
+ qr{(?:unsigned\s+)?char},
+ qr{(?:unsigned\s+)?short},
+ qr{(?:unsigned\s+)?int},
+ qr{(?:unsigned\s+)?long},
+ qr{(?:unsigned\s+)?long\s+int},
+ qr{(?:unsigned\s+)?long\s+long},
+ qr{(?:unsigned\s+)?long\s+long\s+int},
+ qr{unsigned},
+ qr{float},
+ qr{double},
+ qr{bool},
+ qr{struct\s+$Ident},
+ qr{union\s+$Ident},
+ qr{enum\s+$Ident},
+ qr{${Ident}_t},
+ qr{${Ident}_handler},
+ qr{${Ident}_handler_fn},
+);
+our @modifierList = (
+ qr{fastcall},
+);
+
+our $allowed_asm_includes = qr{(?x:
+ irq|
+ memory
+)};
+# memory.h: ARM has a custom one
+
+sub build_types {
+ my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)";
+ my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)";
+ $Modifier = qr{(?:$Attribute|$Sparse|$mods)};
+ $NonptrType = qr{
+ (?:$Modifier\s+|const\s+)*
+ (?:
+ (?:typeof|__typeof__)\s*\(\s*\**\s*$Ident\s*\)|
+ (?:$typeTypedefs\b)|
+ (?:${all}\b)
+ )
+ (?:\s+$Modifier|\s+const)*
+ }x;
+ $Type = qr{
+ $NonptrType
+ (?:[\s\*]+\s*const|[\s\*]+|(?:\s*\[\s*\])+)?
+ (?:\s+$Inline|\s+$Modifier)*
+ }x;
+ $Declare = qr{(?:$Storage\s+)?$Type};
+}
+build_types();
+
+$chk_signoff = 0 if ($file);
+
+my @dep_includes = ();
+my @dep_functions = ();
+my $removal = "Documentation/feature-removal-schedule.txt";
+if ($tree && -f "$root/$removal") {
+ open(my $REMOVE, '<', "$root/$removal") ||
+ die "$P: $removal: open failed - $!\n";
+ while (<$REMOVE>) {
+ if (/^Check:\s+(.*\S)/) {
+ for my $entry (split(/[, ]+/, $1)) {
+ if ($entry =~ m at include/(.*)@) {
+ push(@dep_includes, $1);
+
+ } elsif ($entry !~ m@/@) {
+ push(@dep_functions, $entry);
+ }
+ }
+ }
+ }
+ close($REMOVE);
+}
+
+my @rawlines = ();
+my @lines = ();
+my $vname;
+for my $filename (@ARGV) {
+ my $FILE;
+ if ($file) {
+ open($FILE, '-|', "diff -u /dev/null $filename") ||
+ die "$P: $filename: diff failed - $!\n";
+ } elsif ($filename eq '-') {
+ open($FILE, '<&STDIN');
+ } else {
+ open($FILE, '<', "$filename") ||
+ die "$P: $filename: open failed - $!\n";
+ }
+ if ($filename eq '-') {
+ $vname = 'Your patch';
+ } else {
+ $vname = $filename;
+ }
+ while (<$FILE>) {
+ chomp;
+ push(@rawlines, $_);
+ }
+ close($FILE);
+ if (!process($filename)) {
+ $exit = 1;
+ }
+ @rawlines = ();
+ @lines = ();
+}
+
+exit($exit);
+
+sub top_of_kernel_tree {
+ my ($root) = @_;
+
+ my @tree_check = (
+ "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile",
+ "README", "Documentation", "arch", "include", "drivers",
+ "fs", "init", "ipc", "kernel", "lib", "scripts",
+ );
+
+ foreach my $check (@tree_check) {
+ if (! -e $root . '/' . $check) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+sub expand_tabs {
+ my ($str) = @_;
+
+ my $res = '';
+ my $n = 0;
+ for my $c (split(//, $str)) {
+ if ($c eq "\t") {
+ $res .= ' ';
+ $n++;
+ for (; ($n % 8) != 0; $n++) {
+ $res .= ' ';
+ }
+ next;
+ }
+ $res .= $c;
+ $n++;
+ }
+
+ return $res;
+}
+sub copy_spacing {
+ (my $res = shift) =~ tr/\t/ /c;
+ return $res;
+}
+
+sub line_stats {
+ my ($line) = @_;
+
+ # Drop the diff line leader and expand tabs
+ $line =~ s/^.//;
+ $line = expand_tabs($line);
+
+ # Pick the indent from the front of the line.
+ my ($white) = ($line =~ /^(\s*)/);
+
+ return (length($line), length($white));
+}
+
+my $sanitise_quote = '';
+
+sub sanitise_line_reset {
+ my ($in_comment) = @_;
+
+ if ($in_comment) {
+ $sanitise_quote = '*/';
+ } else {
+ $sanitise_quote = '';
+ }
+}
+sub sanitise_line {
+ my ($line) = @_;
+
+ my $res = '';
+ my $l = '';
+
+ my $qlen = 0;
+ my $off = 0;
+ my $c;
+
+ # Always copy over the diff marker.
+ $res = substr($line, 0, 1);
+
+ for ($off = 1; $off < length($line); $off++) {
+ $c = substr($line, $off, 1);
+
+ # Comments we are wacking completly including the begin
+ # and end, all to $;.
+ if ($sanitise_quote eq '' && substr($line, $off, 2) eq '/*') {
+ $sanitise_quote = '*/';
+
+ substr($res, $off, 2, "$;$;");
+ $off++;
+ next;
+ }
+ if ($sanitise_quote eq '*/' && substr($line, $off, 2) eq '*/') {
+ $sanitise_quote = '';
+ substr($res, $off, 2, "$;$;");
+ $off++;
+ next;
+ }
+ if ($sanitise_quote eq '' && substr($line, $off, 2) eq '//') {
+ $sanitise_quote = '//';
+
+ substr($res, $off, 2, $sanitise_quote);
+ $off++;
+ next;
+ }
+
+ # A \ in a string means ignore the next character.
+ if (($sanitise_quote eq "'" || $sanitise_quote eq '"') &&
+ $c eq "\\") {
+ substr($res, $off, 2, 'XX');
+ $off++;
+ next;
+ }
+ # Regular quotes.
+ if ($c eq "'" || $c eq '"') {
+ if ($sanitise_quote eq '') {
+ $sanitise_quote = $c;
+
+ substr($res, $off, 1, $c);
+ next;
+ } elsif ($sanitise_quote eq $c) {
+ $sanitise_quote = '';
+ }
+ }
+
+ #print "c<$c> SQ<$sanitise_quote>\n";
+ if ($off != 0 && $sanitise_quote eq '*/' && $c ne "\t") {
+ substr($res, $off, 1, $;);
+ } elsif ($off != 0 && $sanitise_quote eq '//' && $c ne "\t") {
+ substr($res, $off, 1, $;);
+ } elsif ($off != 0 && $sanitise_quote && $c ne "\t") {
+ substr($res, $off, 1, 'X');
+ } else {
+ substr($res, $off, 1, $c);
+ }
+ }
+
+ if ($sanitise_quote eq '//') {
+ $sanitise_quote = '';
+ }
+
+ # The pathname on a #include may be surrounded by '<' and '>'.
+ if ($res =~ /^.\s*\#\s*include\s+\<(.*)\>/) {
+ my $clean = 'X' x length($1);
+ $res =~ s@\<.*\>@<$clean>@;
+
+ # The whole of a #error is a string.
+ } elsif ($res =~ /^.\s*\#\s*(?:error|warning)\s+(.*)\b/) {
+ my $clean = 'X' x length($1);
+ $res =~ s@(\#\s*(?:error|warning)\s+).*@$1$clean@;
+ }
+
+ return $res;
+}
+
+sub ctx_statement_block {
+ my ($linenr, $remain, $off) = @_;
+ my $line = $linenr - 1;
+ my $blk = '';
+ my $soff = $off;
+ my $coff = $off - 1;
+ my $coff_set = 0;
+
+ my $loff = 0;
+
+ my $type = '';
+ my $level = 0;
+ my @stack = ();
+ my $p;
+ my $c;
+ my $len = 0;
+
+ my $remainder;
+ while (1) {
+ @stack = (['', 0]) if ($#stack == -1);
+
+ #warn "CSB: blk<$blk> remain<$remain>\n";
+ # If we are about to drop off the end, pull in more
+ # context.
+ if ($off >= $len) {
+ for (; $remain > 0; $line++) {
+ last if (!defined $lines[$line]);
+ next if ($lines[$line] =~ /^-/);
+ $remain--;
+ $loff = $len;
+ $blk .= $lines[$line] . "\n";
+ $len = length($blk);
+ $line++;
+ last;
+ }
+ # Bail if there is no further context.
+ #warn "CSB: blk<$blk> off<$off> len<$len>\n";
+ if ($off >= $len) {
+ last;
+ }
+ }
+ $p = $c;
+ $c = substr($blk, $off, 1);
+ $remainder = substr($blk, $off);
+
+ #warn "CSB: c<$c> type<$type> level<$level> remainder<$remainder> coff_set<$coff_set>\n";
+
+ # Handle nested #if/#else.
+ if ($remainder =~ /^#\s*(?:ifndef|ifdef|if)\s/) {
+ push(@stack, [ $type, $level ]);
+ } elsif ($remainder =~ /^#\s*(?:else|elif)\b/) {
+ ($type, $level) = @{$stack[$#stack - 1]};
+ } elsif ($remainder =~ /^#\s*endif\b/) {
+ ($type, $level) = @{pop(@stack)};
+ }
+
+ # Statement ends at the ';' or a close '}' at the
+ # outermost level.
+ if ($level == 0 && $c eq ';') {
+ last;
+ }
+
+ # An else is really a conditional as long as its not else if
+ if ($level == 0 && $coff_set == 0 &&
+ (!defined($p) || $p =~ /(?:\s|\}|\+)/) &&
+ $remainder =~ /^(else)(?:\s|{)/ &&
+ $remainder !~ /^else\s+if\b/) {
+ $coff = $off + length($1) - 1;
+ $coff_set = 1;
+ #warn "CSB: mark coff<$coff> soff<$soff> 1<$1>\n";
+ #warn "[" . substr($blk, $soff, $coff - $soff + 1) . "]\n";
+ }
+
+ if (($type eq '' || $type eq '(') && $c eq '(') {
+ $level++;
+ $type = '(';
+ }
+ if ($type eq '(' && $c eq ')') {
+ $level--;
+ $type = ($level != 0)? '(' : '';
+
+ if ($level == 0 && $coff < $soff) {
+ $coff = $off;
+ $coff_set = 1;
+ #warn "CSB: mark coff<$coff>\n";
+ }
+ }
+ if (($type eq '' || $type eq '{') && $c eq '{') {
+ $level++;
+ $type = '{';
+ }
+ if ($type eq '{' && $c eq '}') {
+ $level--;
+ $type = ($level != 0)? '{' : '';
+
+ if ($level == 0) {
+ if (substr($blk, $off + 1, 1) eq ';') {
+ $off++;
+ }
+ last;
+ }
+ }
+ $off++;
+ }
+ # We are truly at the end, so shuffle to the next line.
+ if ($off == $len) {
+ $loff = $len + 1;
+ $line++;
+ $remain--;
+ }
+
+ my $statement = substr($blk, $soff, $off - $soff + 1);
+ my $condition = substr($blk, $soff, $coff - $soff + 1);
+
+ #warn "STATEMENT<$statement>\n";
+ #warn "CONDITION<$condition>\n";
+
+ #print "coff<$coff> soff<$off> loff<$loff>\n";
+
+ return ($statement, $condition,
+ $line, $remain + 1, $off - $loff + 1, $level);
+}
+
+sub statement_lines {
+ my ($stmt) = @_;
+
+ # Strip the diff line prefixes and rip blank lines at start and end.
+ $stmt =~ s/(^|\n)./$1/g;
+ $stmt =~ s/^\s*//;
+ $stmt =~ s/\s*$//;
+
+ my @stmt_lines = ($stmt =~ /\n/g);
+
+ return $#stmt_lines + 2;
+}
+
+sub statement_rawlines {
+ my ($stmt) = @_;
+
+ my @stmt_lines = ($stmt =~ /\n/g);
+
+ return $#stmt_lines + 2;
+}
+
+sub statement_block_size {
+ my ($stmt) = @_;
+
+ $stmt =~ s/(^|\n)./$1/g;
+ $stmt =~ s/^\s*{//;
+ $stmt =~ s/}\s*$//;
+ $stmt =~ s/^\s*//;
+ $stmt =~ s/\s*$//;
+
+ my @stmt_lines = ($stmt =~ /\n/g);
+ my @stmt_statements = ($stmt =~ /;/g);
+
+ my $stmt_lines = $#stmt_lines + 2;
+ my $stmt_statements = $#stmt_statements + 1;
+
+ if ($stmt_lines > $stmt_statements) {
+ return $stmt_lines;
+ } else {
+ return $stmt_statements;
+ }
+}
+
+sub ctx_statement_full {
+ my ($linenr, $remain, $off) = @_;
+ my ($statement, $condition, $level);
+
+ my (@chunks);
+
+ # Grab the first conditional/block pair.
+ ($statement, $condition, $linenr, $remain, $off, $level) =
+ ctx_statement_block($linenr, $remain, $off);
+ #print "F: c<$condition> s<$statement> remain<$remain>\n";
+ push(@chunks, [ $condition, $statement ]);
+ if (!($remain > 0 && $condition =~ /^\s*(?:\n[+-])?\s*(?:if|else|do)\b/s)) {
+ return ($level, $linenr, @chunks);
+ }
+
+ # Pull in the following conditional/block pairs and see if they
+ # could continue the statement.
+ for (;;) {
+ ($statement, $condition, $linenr, $remain, $off, $level) =
+ ctx_statement_block($linenr, $remain, $off);
+ #print "C: c<$condition> s<$statement> remain<$remain>\n";
+ last if (!($remain > 0 && $condition =~ /^(?:\s*\n[+-])*\s*(?:else|do)\b/s));
+ #print "C: push\n";
+ push(@chunks, [ $condition, $statement ]);
+ }
+
+ return ($level, $linenr, @chunks);
+}
+
+sub ctx_block_get {
+ my ($linenr, $remain, $outer, $open, $close, $off) = @_;
+ my $line;
+ my $start = $linenr - 1;
+ my $blk = '';
+ my @o;
+ my @c;
+ my @res = ();
+
+ my $level = 0;
+ my @stack = ($level);
+ for ($line = $start; $remain > 0; $line++) {
+ next if ($rawlines[$line] =~ /^-/);
+ $remain--;
+
+ $blk .= $rawlines[$line];
+
+ # Handle nested #if/#else.
+ if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
+ push(@stack, $level);
+ } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
+ $level = $stack[$#stack - 1];
+ } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
+ $level = pop(@stack);
+ }
+
+ foreach my $c (split(//, $lines[$line])) {
+ ##print "C<$c>L<$level><$open$close>O<$off>\n";
+ if ($off > 0) {
+ $off--;
+ next;
+ }
+
+ if ($c eq $close && $level > 0) {
+ $level--;
+ last if ($level == 0);
+ } elsif ($c eq $open) {
+ $level++;
+ }
+ }
+
+ if (!$outer || $level <= 1) {
+ push(@res, $rawlines[$line]);
+ }
+
+ last if ($level == 0);
+ }
+
+ return ($level, @res);
+}
+sub ctx_block_outer {
+ my ($linenr, $remain) = @_;
+
+ my ($level, @r) = ctx_block_get($linenr, $remain, 1, '{', '}', 0);
+ return @r;
+}
+sub ctx_block {
+ my ($linenr, $remain) = @_;
+
+ my ($level, @r) = ctx_block_get($linenr, $remain, 0, '{', '}', 0);
+ return @r;
+}
+sub ctx_statement {
+ my ($linenr, $remain, $off) = @_;
+
+ my ($level, @r) = ctx_block_get($linenr, $remain, 0, '(', ')', $off);
+ return @r;
+}
+sub ctx_block_level {
+ my ($linenr, $remain) = @_;
+
+ return ctx_block_get($linenr, $remain, 0, '{', '}', 0);
+}
+sub ctx_statement_level {
+ my ($linenr, $remain, $off) = @_;
+
+ return ctx_block_get($linenr, $remain, 0, '(', ')', $off);
+}
+
+sub ctx_locate_comment {
+ my ($first_line, $end_line) = @_;
+
+ # Catch a comment on the end of the line itself.
+ my ($current_comment) = ($rawlines[$end_line - 1] =~ m at .*(/\*.*\*/)\s*(?:\\\s*)?$@);
+ return $current_comment if (defined $current_comment);
+
+ # Look through the context and try and figure out if there is a
+ # comment.
+ my $in_comment = 0;
+ $current_comment = '';
+ for (my $linenr = $first_line; $linenr < $end_line; $linenr++) {
+ my $line = $rawlines[$linenr - 1];
+ #warn " $line\n";
+ if ($linenr == $first_line and $line =~ m@^.\s*\*@) {
+ $in_comment = 1;
+ }
+ if ($line =~ m@/\*@) {
+ $in_comment = 1;
+ }
+ if (!$in_comment && $current_comment ne '') {
+ $current_comment = '';
+ }
+ $current_comment .= $line . "\n" if ($in_comment);
+ if ($line =~ m@\*/@) {
+ $in_comment = 0;
+ }
+ }
+
+ chomp($current_comment);
+ return($current_comment);
+}
+sub ctx_has_comment {
+ my ($first_line, $end_line) = @_;
+ my $cmt = ctx_locate_comment($first_line, $end_line);
+
+ ##print "LINE: $rawlines[$end_line - 1 ]\n";
+ ##print "CMMT: $cmt\n";
+
+ return ($cmt ne '');
+}
+
+sub raw_line {
+ my ($linenr, $cnt) = @_;
+
+ my $offset = $linenr - 1;
+ $cnt++;
+
+ my $line;
+ while ($cnt) {
+ $line = $rawlines[$offset++];
+ next if (defined($line) && $line =~ /^-/);
+ $cnt--;
+ }
+
+ return $line;
+}
+
+sub cat_vet {
+ my ($vet) = @_;
+ my ($res, $coded);
+
+ $res = '';
+ while ($vet =~ /([^[:cntrl:]]*)([[:cntrl:]]|$)/g) {
+ $res .= $1;
+ if ($2 ne '') {
+ $coded = sprintf("^%c", unpack('C', $2) + 64);
+ $res .= $coded;
+ }
+ }
+ $res =~ s/$/\$/;
+
+ return $res;
+}
+
+my $av_preprocessor = 0;
+my $av_pending;
+my @av_paren_type;
+my $av_pend_colon;
+
+sub annotate_reset {
+ $av_preprocessor = 0;
+ $av_pending = '_';
+ @av_paren_type = ('E');
+ $av_pend_colon = 'O';
+}
+
+sub annotate_values {
+ my ($stream, $type) = @_;
+
+ my $res;
+ my $var = '_' x length($stream);
+ my $cur = $stream;
+
+ print "$stream\n" if ($dbg_values > 1);
+
+ while (length($cur)) {
+ @av_paren_type = ('E') if ($#av_paren_type < 0);
+ print " <" . join('', @av_paren_type) .
+ "> <$type> <$av_pending>" if ($dbg_values > 1);
+ if ($cur =~ /^(\s+)/o) {
+ print "WS($1)\n" if ($dbg_values > 1);
+ if ($1 =~ /\n/ && $av_preprocessor) {
+ $type = pop(@av_paren_type);
+ $av_preprocessor = 0;
+ }
+
+ } elsif ($cur =~ /^(\(\s*$Type\s*)\)/) {
+ print "CAST($1)\n" if ($dbg_values > 1);
+ push(@av_paren_type, $type);
+ $type = 'C';
+
+ } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
+ print "DECLARE($1)\n" if ($dbg_values > 1);
+ $type = 'T';
+
+ } elsif ($cur =~ /^($Modifier)\s*/) {
+ print "MODIFIER($1)\n" if ($dbg_values > 1);
+ $type = 'T';
+
+ } elsif ($cur =~ /^(\#\s*define\s*$Ident)(\(?)/o) {
+ print "DEFINE($1,$2)\n" if ($dbg_values > 1);
+ $av_preprocessor = 1;
+ push(@av_paren_type, $type);
+ if ($2 ne '') {
+ $av_pending = 'N';
+ }
+ $type = 'E';
+
+ } elsif ($cur =~ /^(\#\s*(?:undef\s*$Ident|include\b))/o) {
+ print "UNDEF($1)\n" if ($dbg_values > 1);
+ $av_preprocessor = 1;
+ push(@av_paren_type, $type);
+
+ } elsif ($cur =~ /^(\#\s*(?:ifdef|ifndef|if))/o) {
+ print "PRE_START($1)\n" if ($dbg_values > 1);
+ $av_preprocessor = 1;
+
+ push(@av_paren_type, $type);
+ push(@av_paren_type, $type);
+ $type = 'E';
+
+ } elsif ($cur =~ /^(\#\s*(?:else|elif))/o) {
+ print "PRE_RESTART($1)\n" if ($dbg_values > 1);
+ $av_preprocessor = 1;
+
+ push(@av_paren_type, $av_paren_type[$#av_paren_type]);
+
+ $type = 'E';
+
+ } elsif ($cur =~ /^(\#\s*(?:endif))/o) {
+ print "PRE_END($1)\n" if ($dbg_values > 1);
+
+ $av_preprocessor = 1;
+
+ # Assume all arms of the conditional end as this
+ # one does, and continue as if the #endif was not here.
+ pop(@av_paren_type);
+ push(@av_paren_type, $type);
+ $type = 'E';
+
+ } elsif ($cur =~ /^(\\\n)/o) {
+ print "PRECONT($1)\n" if ($dbg_values > 1);
+
+ } elsif ($cur =~ /^(__attribute__)\s*\(?/o) {
+ print "ATTR($1)\n" if ($dbg_values > 1);
+ $av_pending = $type;
+ $type = 'N';
+
+ } elsif ($cur =~ /^(sizeof)\s*(\()?/o) {
+ print "SIZEOF($1)\n" if ($dbg_values > 1);
+ if (defined $2) {
+ $av_pending = 'V';
+ }
+ $type = 'N';
+
+ } elsif ($cur =~ /^(if|while|for)\b/o) {
+ print "COND($1)\n" if ($dbg_values > 1);
+ $av_pending = 'E';
+ $type = 'N';
+
+ } elsif ($cur =~/^(case)/o) {
+ print "CASE($1)\n" if ($dbg_values > 1);
+ $av_pend_colon = 'C';
+ $type = 'N';
+
+ } elsif ($cur =~/^(return|else|goto|typeof|__typeof__)\b/o) {
+ print "KEYWORD($1)\n" if ($dbg_values > 1);
+ $type = 'N';
+
+ } elsif ($cur =~ /^(\()/o) {
+ print "PAREN('$1')\n" if ($dbg_values > 1);
+ push(@av_paren_type, $av_pending);
+ $av_pending = '_';
+ $type = 'N';
+
+ } elsif ($cur =~ /^(\))/o) {
+ my $new_type = pop(@av_paren_type);
+ if ($new_type ne '_') {
+ $type = $new_type;
+ print "PAREN('$1') -> $type\n"
+ if ($dbg_values > 1);
+ } else {
+ print "PAREN('$1')\n" if ($dbg_values > 1);
+ }
+
+ } elsif ($cur =~ /^($Ident)\s*\(/o) {
+ print "FUNC($1)\n" if ($dbg_values > 1);
+ $type = 'V';
+ $av_pending = 'V';
+
+ } elsif ($cur =~ /^($Ident\s*):(?:\s*\d+\s*(,|=|;))?/) {
+ if (defined $2 && $type eq 'C' || $type eq 'T') {
+ $av_pend_colon = 'B';
+ } elsif ($type eq 'E') {
+ $av_pend_colon = 'L';
+ }
+ print "IDENT_COLON($1,$type>$av_pend_colon)\n" if ($dbg_values > 1);
+ $type = 'V';
+
+ } elsif ($cur =~ /^($Ident|$Constant)/o) {
+ print "IDENT($1)\n" if ($dbg_values > 1);
+ $type = 'V';
+
+ } elsif ($cur =~ /^($Assignment)/o) {
+ print "ASSIGN($1)\n" if ($dbg_values > 1);
+ $type = 'N';
+
+ } elsif ($cur =~/^(;|{|})/) {
+ print "END($1)\n" if ($dbg_values > 1);
+ $type = 'E';
+ $av_pend_colon = 'O';
+
+ } elsif ($cur =~/^(,)/) {
+ print "COMMA($1)\n" if ($dbg_values > 1);
+ $type = 'C';
+
+ } elsif ($cur =~ /^(\?)/o) {
+ print "QUESTION($1)\n" if ($dbg_values > 1);
+ $type = 'N';
+
+ } elsif ($cur =~ /^(:)/o) {
+ print "COLON($1,$av_pend_colon)\n" if ($dbg_values > 1);
+
+ substr($var, length($res), 1, $av_pend_colon);
+ if ($av_pend_colon eq 'C' || $av_pend_colon eq 'L') {
+ $type = 'E';
+ } else {
+ $type = 'N';
+ }
+ $av_pend_colon = 'O';
+
+ } elsif ($cur =~ /^(\[)/o) {
+ print "CLOSE($1)\n" if ($dbg_values > 1);
+ $type = 'N';
+
+ } elsif ($cur =~ /^(-(?![->])|\+(?!\+)|\*|\&\&|\&)/o) {
+ my $variant;
+
+ print "OPV($1)\n" if ($dbg_values > 1);
+ if ($type eq 'V') {
+ $variant = 'B';
+ } else {
+ $variant = 'U';
+ }
+
+ substr($var, length($res), 1, $variant);
+ $type = 'N';
+
+ } elsif ($cur =~ /^($Operators)/o) {
+ print "OP($1)\n" if ($dbg_values > 1);
+ if ($1 ne '++' && $1 ne '--') {
+ $type = 'N';
+ }
+
+ } elsif ($cur =~ /(^.)/o) {
+ print "C($1)\n" if ($dbg_values > 1);
+ }
+ if (defined $1) {
+ $cur = substr($cur, length($1));
+ $res .= $type x length($1);
+ }
+ }
+
+ return ($res, $var);
+}
+
+sub possible {
+ my ($possible, $line) = @_;
+ my $notPermitted = qr{(?:
+ ^(?:
+ $Modifier|
+ $Storage|
+ $Type|
+ DEFINE_\S+
+ )$|
+ ^(?:
+ goto|
+ return|
+ case|
+ else|
+ asm|__asm__|
+ do
+ )(?:\s|$)|
+ ^(?:typedef|struct|enum)\b
+ )}x;
+ warn "CHECK<$possible> ($line)\n" if ($dbg_possible > 2);
+ if ($possible !~ $notPermitted) {
+ # Check for modifiers.
+ $possible =~ s/\s*$Storage\s*//g;
+ $possible =~ s/\s*$Sparse\s*//g;
+ if ($possible =~ /^\s*$/) {
+
+ } elsif ($possible =~ /\s/) {
+ $possible =~ s/\s*$Type\s*//g;
+ for my $modifier (split(' ', $possible)) {
+ if ($modifier !~ $notPermitted) {
+ warn "MODIFIER: $modifier ($possible) ($line)\n" if ($dbg_possible);
+ push(@modifierList, $modifier);
+ }
+ }
+
+ } else {
+ warn "POSSIBLE: $possible ($line)\n" if ($dbg_possible);
+ push(@typeList, $possible);
+ }
+ build_types();
+ } else {
+ warn "NOTPOSS: $possible ($line)\n" if ($dbg_possible > 1);
+ }
+}
+
+my $prefix = '';
+
+sub report {
+ if (defined $tst_only && $_[0] !~ /\Q$tst_only\E/) {
+ return 0;
+ }
+ my $line = $prefix . $_[0];
+
+ $line = (split('\n', $line))[0] . "\n" if ($terse);
+
+ push(our @report, $line);
+
+ return 1;
+}
+sub report_dump {
+ our @report;
+}
+sub ERROR {
+ if (report("ERROR: $_[0]\n")) {
+ our $clean = 0;
+ our $cnt_error++;
+ }
+}
+sub WARN {
+ if (report("WARNING: $_[0]\n")) {
+ our $clean = 0;
+ our $cnt_warn++;
+ }
+}
+sub CHK {
+ if ($check && report("CHECK: $_[0]\n")) {
+ our $clean = 0;
+ our $cnt_chk++;
+ }
+}
+
+sub check_absolute_file {
+ my ($absolute, $herecurr) = @_;
+ my $file = $absolute;
+
+ ##print "absolute<$absolute>\n";
+
+ # See if any suffix of this path is a path within the tree.
+ while ($file =~ s@^[^/]*/@@) {
+ if (-f "$root/$file") {
+ ##print "file<$file>\n";
+ last;
+ }
+ }
+ if (! -f _) {
+ return 0;
+ }
+
+ # It is, so see if the prefix is acceptable.
+ my $prefix = $absolute;
+ substr($prefix, -length($file)) = '';
+
+ ##print "prefix<$prefix>\n";
+ if ($prefix ne ".../") {
+ WARN("use relative pathname instead of absolute in changelog text\n" . $herecurr);
+ }
+}
+
+sub process {
+ my $filename = shift;
+
+ my $linenr=0;
+ my $prevline="";
+ my $prevrawline="";
+ my $stashline="";
+ my $stashrawline="";
+
+ my $length;
+ my $indent;
+ my $previndent=0;
+ my $stashindent=0;
+
+ our $clean = 1;
+ my $signoff = 0;
+ my $is_patch = 0;
+
+ our @report = ();
+ our $cnt_lines = 0;
+ our $cnt_error = 0;
+ our $cnt_warn = 0;
+ our $cnt_chk = 0;
+
+ # Trace the real file/line as we go.
+ my $realfile = '';
+ my $realline = 0;
+ my $realcnt = 0;
+ my $here = '';
+ my $in_comment = 0;
+ my $comment_edge = 0;
+ my $first_line = 0;
+ my $p1_prefix = '';
+
+ my $prev_values = 'E';
+
+ # suppression flags
+ my %suppress_ifbraces;
+ my %suppress_whiletrailers;
+ my %suppress_export;
+
+ # Pre-scan the patch sanitizing the lines.
+ # Pre-scan the patch looking for any __setup documentation.
+ #
+ my @setup_docs = ();
+ my $setup_docs = 0;
+
+ sanitise_line_reset();
+ my $line;
+ foreach my $rawline (@rawlines) {
+ $linenr++;
+ $line = $rawline;
+
+ if ($rawline=~/^\+\+\+\s+(\S+)/) {
+ $setup_docs = 0;
+ if ($1 =~ m at Documentation/kernel-parameters.txt$@) {
+ $setup_docs = 1;
+ }
+ #next;
+ }
+ if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
+ $realline=$1-1;
+ if (defined $2) {
+ $realcnt=$3+1;
+ } else {
+ $realcnt=1+1;
+ }
+ $in_comment = 0;
+
+ # Guestimate if this is a continuing comment. Run
+ # the context looking for a comment "edge". If this
+ # edge is a close comment then we must be in a comment
+ # at context start.
+ my $edge;
+ my $cnt = $realcnt;
+ for (my $ln = $linenr + 1; $cnt > 0; $ln++) {
+ next if (defined $rawlines[$ln - 1] &&
+ $rawlines[$ln - 1] =~ /^-/);
+ $cnt--;
+ #print "RAW<$rawlines[$ln - 1]>\n";
+ last if (!defined $rawlines[$ln - 1]);
+ if ($rawlines[$ln - 1] =~ m@(/\*|\*/)@ &&
+ $rawlines[$ln - 1] !~ m@"[^"]*(?:/\*|\*/)[^"]*"@) {
+ ($edge) = $1;
+ last;
+ }
+ }
+ if (defined $edge && $edge eq '*/') {
+ $in_comment = 1;
+ }
+
+ # Guestimate if this is a continuing comment. If this
+ # is the start of a diff block and this line starts
+ # ' *' then it is very likely a comment.
+ if (!defined $edge &&
+ $rawlines[$linenr] =~ m@^.\s*(?:\*\*+| \*)(?:\s|$)@)
+ {
+ $in_comment = 1;
+ }
+
+ ##print "COMMENT:$in_comment edge<$edge> $rawline\n";
+ sanitise_line_reset($in_comment);
+
+ } elsif ($realcnt && $rawline =~ /^(?:\+| |$)/) {
+ # Standardise the strings and chars within the input to
+ # simplify matching -- only bother with positive lines.
+ $line = sanitise_line($rawline);
+ }
+ push(@lines, $line);
+
+ if ($realcnt > 1) {
+ $realcnt-- if ($line =~ /^(?:\+| |$)/);
+ } else {
+ $realcnt = 0;
+ }
+
+ #print "==>$rawline\n";
+ #print "-->$line\n";
+
+ if ($setup_docs && $line =~ /^\+/) {
+ push(@setup_docs, $line);
+ }
+ }
+
+ $prefix = '';
+
+ $realcnt = 0;
+ $linenr = 0;
+ foreach my $line (@lines) {
+ $linenr++;
+
+ my $rawline = $rawlines[$linenr - 1];
+
+#extract the line range in the file after the patch is applied
+ if ($line=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
+ $is_patch = 1;
+ $first_line = $linenr + 1;
+ $realline=$1-1;
+ if (defined $2) {
+ $realcnt=$3+1;
+ } else {
+ $realcnt=1+1;
+ }
+ annotate_reset();
+ $prev_values = 'E';
+
+ %suppress_ifbraces = ();
+ %suppress_whiletrailers = ();
+ %suppress_export = ();
+ next;
+
+# track the line number as we move through the hunk, note that
+# new versions of GNU diff omit the leading space on completely
+# blank context lines so we need to count that too.
+ } elsif ($line =~ /^( |\+|$)/) {
+ $realline++;
+ $realcnt-- if ($realcnt != 0);
+
+ # Measure the line length and indent.
+ ($length, $indent) = line_stats($rawline);
+
+ # Track the previous line.
+ ($prevline, $stashline) = ($stashline, $line);
+ ($previndent, $stashindent) = ($stashindent, $indent);
+ ($prevrawline, $stashrawline) = ($stashrawline, $rawline);
+
+ #warn "line<$line>\n";
+
+ } elsif ($realcnt == 1) {
+ $realcnt--;
+ }
+
+ my $hunk_line = ($realcnt != 0);
+
+#make up the handle for any error we report on this line
+ $prefix = "$filename:$realline: " if ($emacs && $file);
+ $prefix = "$filename:$linenr: " if ($emacs && !$file);
+
+ $here = "#$linenr: " if (!$file);
+ $here = "#$realline: " if ($file);
+
+ # extract the filename as it passes
+ if ($line =~ /^diff --git.*?(\S+)$/) {
+ $realfile = $1;
+ $realfile =~ s@^([^/]*)/@@;
+
+ } elsif ($line =~ /^\+\+\+\s+(\S+)/) {
+ $realfile = $1;
+ $realfile =~ s@^([^/]*)/@@;
+
+ $p1_prefix = $1;
+ if (!$file && $tree && $p1_prefix ne '' &&
+ -e "$root/$p1_prefix") {
+ WARN("patch prefix '$p1_prefix' exists, appears to be a -p0 patch\n");
+ }
+
+ if ($realfile =~ m@^include/asm/@) {
+ ERROR("do not modify files in include/asm, change architecture specific files in include/asm-<architecture>\n" . "$here$rawline\n");
+ }
+ next;
+ }
+
+ $here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
+
+ my $hereline = "$here\n$rawline\n";
+ my $herecurr = "$here\n$rawline\n";
+ my $hereprev = "$here\n$prevrawline\n$rawline\n";
+
+ $cnt_lines++ if ($realcnt != 0);
+
+# Check for incorrect file permissions
+ if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
+ my $permhere = $here . "FILE: $realfile\n";
+ if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) {
+ ERROR("do not set execute permissions for source files\n" . $permhere);
+ }
+ }
+
+#check the patch for a signoff:
+ if ($line =~ /^\s*signed-off-by:/i) {
+ # This is a signoff, if ugly, so do not double report.
+ $signoff++;
+ if (!($line =~ /^\s*Signed-off-by:/)) {
+ WARN("Signed-off-by: is the preferred form\n" .
+ $herecurr);
+ }
+ if ($line =~ /^\s*signed-off-by:\S/i) {
+ WARN("space required after Signed-off-by:\n" .
+ $herecurr);
+ }
+ }
+
+# Check for wrappage within a valid hunk of the file
+ if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
+ ERROR("patch seems to be corrupt (line wrapped?)\n" .
+ $herecurr) if (!$emitted_corrupt++);
+ }
+
+# Check for absolute kernel paths.
+ if ($tree) {
+ while ($line =~ m{(?:^|\s)(/\S*)}g) {
+ my $file = $1;
+
+ if ($file =~ m{^(.*?)(?::\d+)+:?$} &&
+ check_absolute_file($1, $herecurr)) {
+ #
+ } else {
+ check_absolute_file($file, $herecurr);
+ }
+ }
+ }
+
+# UTF-8 regex found at http://www.w3.org/International/questions/qa-forms-utf-8.en.php
+ if (($realfile =~ /^$/ || $line =~ /^\+/) &&
+ $rawline !~ m/^$UTF8*$/) {
+ my ($utf8_prefix) = ($rawline =~ /^($UTF8*)/);
+
+ my $blank = copy_spacing($rawline);
+ my $ptr = substr($blank, 0, length($utf8_prefix)) . "^";
+ my $hereptr = "$hereline$ptr\n";
+
+ ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr);
+ }
+
+# ignore non-hunk lines and lines being removed
+ next if (!$hunk_line || $line =~ /^-/);
+
+#trailing whitespace
+ if ($line =~ /^\+.*\015/) {
+ my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+ ERROR("DOS line endings\n" . $herevet);
+
+ } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
+ my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+ ERROR("trailing whitespace\n" . $herevet);
+ $rpt_cleaners = 1;
+ }
+
+# check for Kconfig help text having a real description
+# Only applies when adding the entry originally, after that we do not have
+# sufficient context to determine whether it is indeed long enough.
+ if ($realfile =~ /Kconfig/ &&
+ $line =~ /\+\s*(?:---)?help(?:---)?$/) {
+ my $length = 0;
+ my $cnt = $realcnt;
+ my $ln = $linenr + 1;
+ my $f;
+ my $is_end = 0;
+ while ($cnt > 0 && defined $lines[$ln - 1]) {
+ $f = $lines[$ln - 1];
+ $cnt-- if ($lines[$ln - 1] !~ /^-/);
+ $is_end = $lines[$ln - 1] =~ /^\+/;
+ $ln++;
+
+ next if ($f =~ /^-/);
+ $f =~ s/^.//;
+ $f =~ s/#.*//;
+ $f =~ s/^\s+//;
+ next if ($f =~ /^$/);
+ if ($f =~ /^\s*config\s/) {
+ $is_end = 1;
+ last;
+ }
+ $length++;
+ }
+ WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4);
+ #print "is_end<$is_end> length<$length>\n";
+ }
+
+# check we are in a valid source file if not then ignore this hunk
+ next if ($realfile !~ /\.(h|c|s|S|pl|sh)$/);
+
+#80 column limit
+ if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
+ $rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
+ !($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ ||
+ $line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) &&
+ $length > 80)
+ {
+ WARN("line over 80 characters\n" . $herecurr);
+ }
+
+# check for spaces before a quoted newline
+ if ($rawline =~ /^.*\".*\s\\n/) {
+ WARN("unnecessary whitespace before a quoted newline\n" . $herecurr);
+ }
+
+# check for adding lines without a newline.
+ if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
+ WARN("adding a line without newline at end of file\n" . $herecurr);
+ }
+
+# Blackfin: use hi/lo macros
+ if ($realfile =~ m at arch/blackfin/.*\.S$@) {
+ if ($line =~ /\.[lL][[:space:]]*=.*&[[:space:]]*0x[fF][fF][fF][fF]/) {
+ my $herevet = "$here\n" . cat_vet($line) . "\n";
+ ERROR("use the LO() macro, not (... & 0xFFFF)\n" . $herevet);
+ }
+ if ($line =~ /\.[hH][[:space:]]*=.*>>[[:space:]]*16/) {
+ my $herevet = "$here\n" . cat_vet($line) . "\n";
+ ERROR("use the HI() macro, not (... >> 16)\n" . $herevet);
+ }
+ }
+
+# check we are in a valid source file C or perl if not then ignore this hunk
+ next if ($realfile !~ /\.(h|c|pl)$/);
+
+# at the beginning of a line any tabs must come first and anything
+# more than 8 must use tabs.
+ if ($rawline =~ /^\+\s* \t\s*\S/ ||
+ $rawline =~ /^\+\s* \s*/) {
+ my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+ ERROR("code indent should use tabs where possible\n" . $herevet);
+ $rpt_cleaners = 1;
+ }
+
+# check for space before tabs.
+ if ($rawline =~ /^\+/ && $rawline =~ / \t/) {
+ my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+ WARN("please, no space before tabs\n" . $herevet);
+ }
+
+# check for spaces at the beginning of a line.
+# Exceptions:
+# 1) within comments
+# 2) indented preprocessor commands
+# 3) hanging labels
+ if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/) {
+ my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+ WARN("please, no spaces at the start of a line\n" . $herevet);
+ }
+
+# check we are in a valid C source file if not then ignore this hunk
+ next if ($realfile !~ /\.(h|c)$/);
+
+# check for RCS/CVS revision markers
+ if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
+ WARN("CVS style keyword markers, these will _not_ be updated\n". $herecurr);
+ }
+
+# Blackfin: don't use __builtin_bfin_[cs]sync
+ if ($line =~ /__builtin_bfin_csync/) {
+ my $herevet = "$here\n" . cat_vet($line) . "\n";
+ ERROR("use the CSYNC() macro in asm/blackfin.h\n" . $herevet);
+ }
+ if ($line =~ /__builtin_bfin_ssync/) {
+ my $herevet = "$here\n" . cat_vet($line) . "\n";
+ ERROR("use the SSYNC() macro in asm/blackfin.h\n" . $herevet);
+ }
+
+# Check for potential 'bare' types
+ my ($stat, $cond, $line_nr_next, $remain_next, $off_next,
+ $realline_next);
+ if ($realcnt && $line =~ /.\s*\S/) {
+ ($stat, $cond, $line_nr_next, $remain_next, $off_next) =
+ ctx_statement_block($linenr, $realcnt, 0);
+ $stat =~ s/\n./\n /g;
+ $cond =~ s/\n./\n /g;
+
+ # Find the real next line.
+ $realline_next = $line_nr_next;
+ if (defined $realline_next &&
+ (!defined $lines[$realline_next - 1] ||
+ substr($lines[$realline_next - 1], $off_next) =~ /^\s*$/)) {
+ $realline_next++;
+ }
+
+ my $s = $stat;
+ $s =~ s/{.*$//s;
+
+ # Ignore goto labels.
+ if ($s =~ /$Ident:\*$/s) {
+
+ # Ignore functions being called
+ } elsif ($s =~ /^.\s*$Ident\s*\(/s) {
+
+ } elsif ($s =~ /^.\s*else\b/s) {
+
+ # declarations always start with types
+ } elsif ($prev_values eq 'E' && $s =~ /^.\s*(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?((?:\s*$Ident)+?)\b(?:\s+$Sparse)?\s*\**\s*(?:$Ident|\(\*[^\)]*\))(?:\s*$Modifier)?\s*(?:;|=|,|\()/s) {
+ my $type = $1;
+ $type =~ s/\s+/ /g;
+ possible($type, "A:" . $s);
+
+ # definitions in global scope can only start with types
+ } elsif ($s =~ /^.(?:$Storage\s+)?(?:$Inline\s+)?(?:const\s+)?($Ident)\b\s*(?!:)/s) {
+ possible($1, "B:" . $s);
+ }
+
+ # any (foo ... *) is a pointer cast, and foo is a type
+ while ($s =~ /\(($Ident)(?:\s+$Sparse)*[\s\*]+\s*\)/sg) {
+ possible($1, "C:" . $s);
+ }
+
+ # Check for any sort of function declaration.
+ # int foo(something bar, other baz);
+ # void (*store_gdt)(x86_descr_ptr *);
+ if ($prev_values eq 'E' && $s =~ /^(.(?:typedef\s*)?(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*(?:\b$Ident|\(\*\s*$Ident\))\s*)\(/s) {
+ my ($name_len) = length($1);
+
+ my $ctx = $s;
+ substr($ctx, 0, $name_len + 1, '');
+ $ctx =~ s/\)[^\)]*$//;
+
+ for my $arg (split(/\s*,\s*/, $ctx)) {
+ if ($arg =~ /^(?:const\s+)?($Ident)(?:\s+$Sparse)*\s*\**\s*(:?\b$Ident)?$/s || $arg =~ /^($Ident)$/s) {
+
+ possible($1, "D:" . $s);
+ }
+ }
+ }
+
+ }
+
+#
+# Checks which may be anchored in the context.
+#
+
+# Check for switch () and associated case and default
+# statements should be at the same indent.
+ if ($line=~/\bswitch\s*\(.*\)/) {
+ my $err = '';
+ my $sep = '';
+ my @ctx = ctx_block_outer($linenr, $realcnt);
+ shift(@ctx);
+ for my $ctx (@ctx) {
+ my ($clen, $cindent) = line_stats($ctx);
+ if ($ctx =~ /^\+\s*(case\s+|default:)/ &&
+ $indent != $cindent) {
+ $err .= "$sep$ctx\n";
+ $sep = '';
+ } else {
+ $sep = "[...]\n";
+ }
+ }
+ if ($err ne '') {
+ ERROR("switch and case should be at the same indent\n$hereline$err");
+ }
+ }
+
+# if/while/etc brace do not go on next line, unless defining a do while loop,
+# or if that brace on the next line is for something else
+ if ($line =~ /(.*)\b((?:if|while|for|switch)\s*\(|do\b|else\b)/ && $line !~ /^.\s*\#/) {
+ my $pre_ctx = "$1$2";
+
+ my ($level, @ctx) = ctx_statement_level($linenr, $realcnt, 0);
+ my $ctx_cnt = $realcnt - $#ctx - 1;
+ my $ctx = join("\n", @ctx);
+
+ my $ctx_ln = $linenr;
+ my $ctx_skip = $realcnt;
+
+ while ($ctx_skip > $ctx_cnt || ($ctx_skip == $ctx_cnt &&
+ defined $lines[$ctx_ln - 1] &&
+ $lines[$ctx_ln - 1] =~ /^-/)) {
+ ##print "SKIP<$ctx_skip> CNT<$ctx_cnt>\n";
+ $ctx_skip-- if (!defined $lines[$ctx_ln - 1] || $lines[$ctx_ln - 1] !~ /^-/);
+ $ctx_ln++;
+ }
+
+ #print "realcnt<$realcnt> ctx_cnt<$ctx_cnt>\n";
+ #print "pre<$pre_ctx>\nline<$line>\nctx<$ctx>\nnext<$lines[$ctx_ln - 1]>\n";
+
+ if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
+ ERROR("that open brace { should be on the previous line\n" .
+ "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
+ }
+ if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
+ $ctx =~ /\)\s*\;\s*$/ &&
+ defined $lines[$ctx_ln - 1])
+ {
+ my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
+ if ($nindent > $indent) {
+ WARN("trailing semicolon indicates no statements, indent implies otherwise\n" .
+ "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
+ }
+ }
+ }
+
+# Check relative indent for conditionals and blocks.
+ if ($line =~ /\b(?:(?:if|while|for)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
+ my ($s, $c) = ($stat, $cond);
+
+ substr($s, 0, length($c), '');
+
+ # Make sure we remove the line prefixes as we have
+ # none on the first line, and are going to readd them
+ # where necessary.
+ $s =~ s/\n./\n/gs;
+
+ # Find out how long the conditional actually is.
+ my @newlines = ($c =~ /\n/gs);
+ my $cond_lines = 1 + $#newlines;
+
+ # We want to check the first line inside the block
+ # starting at the end of the conditional, so remove:
+ # 1) any blank line termination
+ # 2) any opening brace { on end of the line
+ # 3) any do (...) {
+ my $continuation = 0;
+ my $check = 0;
+ $s =~ s/^.*\bdo\b//;
+ $s =~ s/^\s*{//;
+ if ($s =~ s/^\s*\\//) {
+ $continuation = 1;
+ }
+ if ($s =~ s/^\s*?\n//) {
+ $check = 1;
+ $cond_lines++;
+ }
+
+ # Also ignore a loop construct at the end of a
+ # preprocessor statement.
+ if (($prevline =~ /^.\s*#\s*define\s/ ||
+ $prevline =~ /\\\s*$/) && $continuation == 0) {
+ $check = 0;
+ }
+
+ my $cond_ptr = -1;
+ $continuation = 0;
+ while ($cond_ptr != $cond_lines) {
+ $cond_ptr = $cond_lines;
+
+ # If we see an #else/#elif then the code
+ # is not linear.
+ if ($s =~ /^\s*\#\s*(?:else|elif)/) {
+ $check = 0;
+ }
+
+ # Ignore:
+ # 1) blank lines, they should be at 0,
+ # 2) preprocessor lines, and
+ # 3) labels.
+ if ($continuation ||
+ $s =~ /^\s*?\n/ ||
+ $s =~ /^\s*#\s*?/ ||
+ $s =~ /^\s*$Ident\s*:/) {
+ $continuation = ($s =~ /^.*?\\\n/) ? 1 : 0;
+ if ($s =~ s/^.*?\n//) {
+ $cond_lines++;
+ }
+ }
+ }
+
+ my (undef, $sindent) = line_stats("+" . $s);
+ my $stat_real = raw_line($linenr, $cond_lines);
+
+ # Check if either of these lines are modified, else
+ # this is not this patch's fault.
+ if (!defined($stat_real) ||
+ $stat !~ /^\+/ && $stat_real !~ /^\+/) {
+ $check = 0;
+ }
+ if (defined($stat_real) && $cond_lines > 1) {
+ $stat_real = "[...]\n$stat_real";
+ }
+
+ #print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n";
+
+ if ($check && (($sindent % 8) != 0 ||
+ ($sindent <= $indent && $s ne ''))) {
+ WARN("suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
+ }
+ }
+
+ # Track the 'values' across context and added lines.
+ my $opline = $line; $opline =~ s/^./ /;
+ my ($curr_values, $curr_vars) =
+ annotate_values($opline . "\n", $prev_values);
+ $curr_values = $prev_values . $curr_values;
+ if ($dbg_values) {
+ my $outline = $opline; $outline =~ s/\t/ /g;
+ print "$linenr > .$outline\n";
+ print "$linenr > $curr_values\n";
+ print "$linenr > $curr_vars\n";
+ }
+ $prev_values = substr($curr_values, -1);
+
+#ignore lines not being added
+ if ($line=~/^[^\+]/) {next;}
+
+# TEST: allow direct testing of the type matcher.
+ if ($dbg_type) {
+ if ($line =~ /^.\s*$Declare\s*$/) {
+ ERROR("TEST: is type\n" . $herecurr);
+ } elsif ($dbg_type > 1 && $line =~ /^.+($Declare)/) {
+ ERROR("TEST: is not type ($1 is)\n". $herecurr);
+ }
+ next;
+ }
+# TEST: allow direct testing of the attribute matcher.
+ if ($dbg_attr) {
+ if ($line =~ /^.\s*$Modifier\s*$/) {
+ ERROR("TEST: is attr\n" . $herecurr);
+ } elsif ($dbg_attr > 1 && $line =~ /^.+($Modifier)/) {
+ ERROR("TEST: is not attr ($1 is)\n". $herecurr);
+ }
+ next;
+ }
+
+# check for initialisation to aggregates open brace on the next line
+ if ($line =~ /^.\s*{/ &&
+ $prevline =~ /(?:^|[^=])=\s*$/) {
+ ERROR("that open brace { should be on the previous line\n" . $hereprev);
+ }
+
+#
+# Checks which are anchored on the added line.
+#
+
+# check for malformed paths in #include statements (uses RAW line)
+ if ($rawline =~ m{^.\s*\#\s*include\s+[<"](.*)[">]}) {
+ my $path = $1;
+ if ($path =~ m{//}) {
+ ERROR("malformed #include filename\n" .
+ $herecurr);
+ }
+ }
+
+# no C99 // comments
+ if ($line =~ m{//}) {
+ ERROR("do not use C99 // comments\n" . $herecurr);
+ }
+ # Remove C99 comments.
+ $line =~ s@//.*@@;
+ $opline =~ s@//.*@@;
+
+# EXPORT_SYMBOL should immediately follow the thing it is exporting, consider
+# the whole statement.
+#print "APW <$lines[$realline_next - 1]>\n";
+ if (defined $realline_next &&
+ exists $lines[$realline_next - 1] &&
+ !defined $suppress_export{$realline_next} &&
+ ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
+ $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+ # Handle definitions which produce identifiers with
+ # a prefix:
+ # XXX(foo);
+ # EXPORT_SYMBOL(something_foo);
+ my $name = $1;
+ if ($stat =~ /^.([A-Z_]+)\s*\(\s*($Ident)/ &&
+ $name =~ /^${Ident}_$2/) {
+#print "FOO C name<$name>\n";
+ $suppress_export{$realline_next} = 1;
+
+ } elsif ($stat !~ /(?:
+ \n.}\s*$|
+ ^.DEFINE_$Ident\(\Q$name\E\)|
+ ^.DECLARE_$Ident\(\Q$name\E\)|
+ ^.LIST_HEAD\(\Q$name\E\)|
+ ^.(?:$Storage\s+)?$Type\s*\(\s*\*\s*\Q$name\E\s*\)\s*\(|
+ \b\Q$name\E(?:\s+$Attribute)*\s*(?:;|=|\[|\()
+ )/x) {
+#print "FOO A<$lines[$realline_next - 1]> stat<$stat> name<$name>\n";
+ $suppress_export{$realline_next} = 2;
+ } else {
+ $suppress_export{$realline_next} = 1;
+ }
+ }
+ if (!defined $suppress_export{$linenr} &&
+ $prevline =~ /^.\s*$/ &&
+ ($line =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
+ $line =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+#print "FOO B <$lines[$linenr - 1]>\n";
+ $suppress_export{$linenr} = 2;
+ }
+ if (defined $suppress_export{$linenr} &&
+ $suppress_export{$linenr} == 2) {
+ WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
+ }
+
+# check for global initialisers.
+ if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) {
+ ERROR("do not initialise globals to 0 or NULL\n" .
+ $herecurr);
+ }
+# check for static initialisers.
+ if ($line =~ /\bstatic\s.*=\s*(0|NULL|false)\s*;/) {
+ ERROR("do not initialise statics to 0 or NULL\n" .
+ $herecurr);
+ }
+
+# check for new typedefs, only function parameters and sparse annotations
+# make sense.
+ if ($line =~ /\btypedef\s/ &&
+ $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ &&
+ $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ &&
+ $line !~ /\b$typeTypedefs\b/ &&
+ $line !~ /\b__bitwise(?:__|)\b/) {
+ WARN("do not add new typedefs\n" . $herecurr);
+ }
+
+# * goes on variable not on type
+ # (char*[ const])
+ if ($line =~ m{\($NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)\)}) {
+ my ($from, $to) = ($1, $1);
+
+ # Should start with a space.
+ $to =~ s/^(\S)/ $1/;
+ # Should not end with a space.
+ $to =~ s/\s+$//;
+ # '*'s should not have spaces between.
+ while ($to =~ s/\*\s+\*/\*\*/) {
+ }
+
+ #print "from<$from> to<$to>\n";
+ if ($from ne $to) {
+ ERROR("\"(foo$from)\" should be \"(foo$to)\"\n" . $herecurr);
+ }
+ } elsif ($line =~ m{\b$NonptrType(\s*(?:$Modifier\b\s*|\*\s*)+)($Ident)}) {
+ my ($from, $to, $ident) = ($1, $1, $2);
+
+ # Should start with a space.
+ $to =~ s/^(\S)/ $1/;
+ # Should not end with a space.
+ $to =~ s/\s+$//;
+ # '*'s should not have spaces between.
+ while ($to =~ s/\*\s+\*/\*\*/) {
+ }
+ # Modifiers should have spaces.
+ $to =~ s/(\b$Modifier$)/$1 /;
+
+ #print "from<$from> to<$to> ident<$ident>\n";
+ if ($from ne $to && $ident !~ /^$Modifier$/) {
+ ERROR("\"foo${from}bar\" should be \"foo${to}bar\"\n" . $herecurr);
+ }
+ }
+
+# # no BUG() or BUG_ON()
+# if ($line =~ /\b(BUG|BUG_ON)\b/) {
+# print "Try to use WARN_ON & Recovery code rather than BUG() or BUG_ON()\n";
+# print "$herecurr";
+# $clean = 0;
+# }
+
+ if ($line =~ /\bLINUX_VERSION_CODE\b/) {
+ WARN("LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
+ }
+
+# printk should use KERN_* levels. Note that follow on printk's on the
+# same line do not need a level, so we use the current block context
+# to try and find and validate the current printk. In summary the current
+# printk includes all preceeding printk's which have no newline on the end.
+# we assume the first bad printk is the one to report.
+ if ($line =~ /\bprintk\((?!KERN_)\s*"/) {
+ my $ok = 0;
+ for (my $ln = $linenr - 1; $ln >= $first_line; $ln--) {
+ #print "CHECK<$lines[$ln - 1]\n";
+ # we have a preceeding printk if it ends
+ # with "\n" ignore it, else it is to blame
+ if ($lines[$ln - 1] =~ m{\bprintk\(}) {
+ if ($rawlines[$ln - 1] !~ m{\\n"}) {
+ $ok = 1;
+ }
+ last;
+ }
+ }
+ if ($ok == 0) {
+ WARN("printk() should include KERN_ facility level\n" . $herecurr);
+ }
+ }
+
+# function brace can't be on same line, except for #defines of do while,
+# or if closed on same line
+ if (($line=~/$Type\s*$Ident\(.*\).*\s{/) and
+ !($line=~/\#\s*define.*do\s{/) and !($line=~/}/)) {
+ ERROR("open brace '{' following function declarations go on the next line\n" . $herecurr);
+ }
+
+# open braces for enum, union and struct go on the same line.
+ if ($line =~ /^.\s*{/ &&
+ $prevline =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?\s*$/) {
+ ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
+ }
+
+# missing space after union, struct or enum definition
+ if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
+ WARN("missing space after $1 definition\n" . $herecurr);
+ }
+
+# check for spacing round square brackets; allowed:
+# 1. with a type on the left -- int [] a;
+# 2. at the beginning of a line for slice initialisers -- [0...10] = 5,
+# 3. inside a curly brace -- = { [0...10] = 5 }
+ while ($line =~ /(.*?\s)\[/g) {
+ my ($where, $prefix) = ($-[1], $1);
+ if ($prefix !~ /$Type\s+$/ &&
+ ($where != 0 || $prefix !~ /^.\s+$/) &&
+ $prefix !~ /{\s+$/) {
+ ERROR("space prohibited before open square bracket '['\n" . $herecurr);
+ }
+ }
+
+# check for spaces between functions and their parentheses.
+ while ($line =~ /($Ident)\s+\(/g) {
+ my $name = $1;
+ my $ctx_before = substr($line, 0, $-[1]);
+ my $ctx = "$ctx_before$name";
+
+ # Ignore those directives where spaces _are_ permitted.
+ if ($name =~ /^(?:
+ if|for|while|switch|return|case|
+ volatile|__volatile__|
+ __attribute__|format|__extension__|
+ asm|__asm__)$/x)
+ {
+
+ # cpp #define statements have non-optional spaces, ie
+ # if there is a space between the name and the open
+ # parenthesis it is simply not a parameter group.
+ } elsif ($ctx_before =~ /^.\s*\#\s*define\s*$/) {
+
+ # cpp #elif statement condition may start with a (
+ } elsif ($ctx =~ /^.\s*\#\s*elif\s*$/) {
+
+ # If this whole things ends with a type its most
+ # likely a typedef for a function.
+ } elsif ($ctx =~ /$Type$/) {
+
+ } else {
+ WARN("space prohibited between function name and open parenthesis '('\n" . $herecurr);
+ }
+ }
+# Check operator spacing.
+ if (!($line=~/\#\s*include/)) {
+ my $ops = qr{
+ <<=|>>=|<=|>=|==|!=|
+ \+=|-=|\*=|\/=|%=|\^=|\|=|&=|
+ =>|->|<<|>>|<|>|=|!|~|
+ &&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
+ \?|:
+ }x;
+ my @elements = split(/($ops|;)/, $opline);
+ my $off = 0;
+
+ my $blank = copy_spacing($opline);
+
+ for (my $n = 0; $n < $#elements; $n += 2) {
+ $off += length($elements[$n]);
+
+ # Pick up the preceeding and succeeding characters.
+ my $ca = substr($opline, 0, $off);
+ my $cc = '';
+ if (length($opline) >= ($off + length($elements[$n + 1]))) {
+ $cc = substr($opline, $off + length($elements[$n + 1]));
+ }
+ my $cb = "$ca$;$cc";
+
+ my $a = '';
+ $a = 'V' if ($elements[$n] ne '');
+ $a = 'W' if ($elements[$n] =~ /\s$/);
+ $a = 'C' if ($elements[$n] =~ /$;$/);
+ $a = 'B' if ($elements[$n] =~ /(\[|\()$/);
+ $a = 'O' if ($elements[$n] eq '');
+ $a = 'E' if ($ca =~ /^\s*$/);
+
+ my $op = $elements[$n + 1];
+
+ my $c = '';
+ if (defined $elements[$n + 2]) {
+ $c = 'V' if ($elements[$n + 2] ne '');
+ $c = 'W' if ($elements[$n + 2] =~ /^\s/);
+ $c = 'C' if ($elements[$n + 2] =~ /^$;/);
+ $c = 'B' if ($elements[$n + 2] =~ /^(\)|\]|;)/);
+ $c = 'O' if ($elements[$n + 2] eq '');
+ $c = 'E' if ($elements[$n + 2] =~ /^\s*\\$/);
+ } else {
+ $c = 'E';
+ }
+
+ my $ctx = "${a}x${c}";
+
+ my $at = "(ctx:$ctx)";
+
+ my $ptr = substr($blank, 0, $off) . "^";
+ my $hereptr = "$hereline$ptr\n";
+
+ # Pull out the value of this operator.
+ my $op_type = substr($curr_values, $off + 1, 1);
+
+ # Get the full operator variant.
+ my $opv = $op . substr($curr_vars, $off, 1);
+
+ # Ignore operators passed as parameters.
+ if ($op_type ne 'V' &&
+ $ca =~ /\s$/ && $cc =~ /^\s*,/) {
+
+# # Ignore comments
+# } elsif ($op =~ /^$;+$/) {
+
+ # ; should have either the end of line or a space or \ after it
+ } elsif ($op eq ';') {
+ if ($ctx !~ /.x[WEBC]/ &&
+ $cc !~ /^\\/ && $cc !~ /^;/) {
+ ERROR("space required after that '$op' $at\n" . $hereptr);
+ }
+
+ # // is a comment
+ } elsif ($op eq '//') {
+
+ # No spaces for:
+ # ->
+ # : when part of a bitfield
+ } elsif ($op eq '->' || $opv eq ':B') {
+ if ($ctx =~ /Wx.|.xW/) {
+ ERROR("spaces prohibited around that '$op' $at\n" . $hereptr);
+ }
+
+ # , must have a space on the right.
+ } elsif ($op eq ',') {
+ if ($ctx !~ /.x[WEC]/ && $cc !~ /^}/) {
+ ERROR("space required after that '$op' $at\n" . $hereptr);
+ }
+
+ # '*' as part of a type definition -- reported already.
+ } elsif ($opv eq '*_') {
+ #warn "'*' is part of type\n";
+
+ # unary operators should have a space before and
+ # none after. May be left adjacent to another
+ # unary operator, or a cast
+ } elsif ($op eq '!' || $op eq '~' ||
+ $opv eq '*U' || $opv eq '-U' ||
+ $opv eq '&U' || $opv eq '&&U') {
+ if ($ctx !~ /[WEBC]x./ && $ca !~ /(?:\)|!|~|\*|-|\&|\||\+\+|\-\-|\{)$/) {
+ ERROR("space required before that '$op' $at\n" . $hereptr);
+ }
+ if ($op eq '*' && $cc =~/\s*$Modifier\b/) {
+ # A unary '*' may be const
+
+ } elsif ($ctx =~ /.xW/) {
+ ERROR("space prohibited after that '$op' $at\n" . $hereptr);
+ }
+
+ # unary ++ and unary -- are allowed no space on one side.
+ } elsif ($op eq '++' or $op eq '--') {
+ if ($ctx !~ /[WEOBC]x[^W]/ && $ctx !~ /[^W]x[WOBEC]/) {
+ ERROR("space required one side of that '$op' $at\n" . $hereptr);
+ }
+ if ($ctx =~ /Wx[BE]/ ||
+ ($ctx =~ /Wx./ && $cc =~ /^;/)) {
+ ERROR("space prohibited before that '$op' $at\n" . $hereptr);
+ }
+ if ($ctx =~ /ExW/) {
+ ERROR("space prohibited after that '$op' $at\n" . $hereptr);
+ }
+
+
+ # << and >> may either have or not have spaces both sides
+ } elsif ($op eq '<<' or $op eq '>>' or
+ $op eq '&' or $op eq '^' or $op eq '|' or
+ $op eq '+' or $op eq '-' or
+ $op eq '*' or $op eq '/' or
+ $op eq '%')
+ {
+ if ($ctx =~ /Wx[^WCE]|[^WCE]xW/) {
+ ERROR("need consistent spacing around '$op' $at\n" .
+ $hereptr);
+ }
+
+ # A colon needs no spaces before when it is
+ # terminating a case value or a label.
+ } elsif ($opv eq ':C' || $opv eq ':L') {
+ if ($ctx =~ /Wx./) {
+ ERROR("space prohibited before that '$op' $at\n" . $hereptr);
+ }
+
+ # All the others need spaces both sides.
+ } elsif ($ctx !~ /[EWC]x[CWE]/) {
+ my $ok = 0;
+
+ # Ignore email addresses <foo at bar>
+ if (($op eq '<' &&
+ $cc =~ /^\S+\@\S+>/) ||
+ ($op eq '>' &&
+ $ca =~ /<\S+\@\S+$/))
+ {
+ $ok = 1;
+ }
+
+ # Ignore ?:
+ if (($opv eq ':O' && $ca =~ /\?$/) ||
+ ($op eq '?' && $cc =~ /^:/)) {
+ $ok = 1;
+ }
+
+ if ($ok == 0) {
+ ERROR("spaces required around that '$op' $at\n" . $hereptr);
+ }
+ }
+ $off += length($elements[$n + 1]);
+ }
+ }
+
+# check for multiple assignments
+ if ($line =~ /^.\s*$Lval\s*=\s*$Lval\s*=(?!=)/) {
+ CHK("multiple assignments should be avoided\n" . $herecurr);
+ }
+
+## # check for multiple declarations, allowing for a function declaration
+## # continuation.
+## if ($line =~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Ident.*/ &&
+## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) {
+##
+## # Remove any bracketed sections to ensure we do not
+## # falsly report the parameters of functions.
+## my $ln = $line;
+## while ($ln =~ s/\([^\(\)]*\)//g) {
+## }
+## if ($ln =~ /,/) {
+## WARN("declaring multiple variables together should be avoided\n" . $herecurr);
+## }
+## }
+
+#need space before brace following if, while, etc
+ if (($line =~ /\(.*\){/ && $line !~ /\($Type\){/) ||
+ $line =~ /do{/) {
+ ERROR("space required before the open brace '{'\n" . $herecurr);
+ }
+
+# closing brace should have a space following it when it has anything
+# on the line
+ if ($line =~ /}(?!(?:,|;|\)))\S/) {
+ ERROR("space required after that close brace '}'\n" . $herecurr);
+ }
+
+# check spacing on square brackets
+ if ($line =~ /\[\s/ && $line !~ /\[\s*$/) {
+ ERROR("space prohibited after that open square bracket '['\n" . $herecurr);
+ }
+ if ($line =~ /\s\]/) {
+ ERROR("space prohibited before that close square bracket ']'\n" . $herecurr);
+ }
+
+# check spacing on parentheses
+ if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
+ $line !~ /for\s*\(\s+;/) {
+ ERROR("space prohibited after that open parenthesis '('\n" . $herecurr);
+ }
+ if ($line =~ /(\s+)\)/ && $line !~ /^.\s*\)/ &&
+ $line !~ /for\s*\(.*;\s+\)/ &&
+ $line !~ /:\s+\)/) {
+ ERROR("space prohibited before that close parenthesis ')'\n" . $herecurr);
+ }
+
+#goto labels aren't indented, allow a single space however
+ if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and
+ !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) {
+ WARN("labels should not be indented\n" . $herecurr);
+ }
+
+# Return is not a function.
+ if (defined($stat) && $stat =~ /^.\s*return(\s*)(\(.*);/s) {
+ my $spacing = $1;
+ my $value = $2;
+
+ # Flatten any parentheses
+ $value =~ s/\(/ \(/g;
+ $value =~ s/\)/\) /g;
+ while ($value =~ s/\[[^\{\}]*\]/1/ ||
+ $value !~ /(?:$Ident|-?$Constant)\s*
+ $Compare\s*
+ (?:$Ident|-?$Constant)/x &&
+ $value =~ s/\([^\(\)]*\)/1/) {
+ }
+#print "value<$value>\n";
+ if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) {
+ ERROR("return is not a function, parentheses are not required\n" . $herecurr);
+
+ } elsif ($spacing !~ /\s+/) {
+ ERROR("space required before the open parenthesis '('\n" . $herecurr);
+ }
+ }
+# Return of what appears to be an errno should normally be -'ve
+ if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
+ my $name = $1;
+ if ($name ne 'EOF' && $name ne 'ERROR') {
+ CHK("return of an errno should typically be -ve (return -$1)\n" . $herecurr);
+ }
+ }
+
+# Need a space before open parenthesis after if, while etc
+ if ($line=~/\b(if|while|for|switch)\(/) {
+ ERROR("space required before the open parenthesis '('\n" . $herecurr);
+ }
+
+# Check for illegal assignment in if conditional -- and check for trailing
+# statements after the conditional.
+ if ($line =~ /do\s*(?!{)/) {
+ my ($stat_next) = ctx_statement_block($line_nr_next,
+ $remain_next, $off_next);
+ $stat_next =~ s/\n./\n /g;
+ ##print "stat<$stat> stat_next<$stat_next>\n";
+
+ if ($stat_next =~ /^\s*while\b/) {
+ # If the statement carries leading newlines,
+ # then count those as offsets.
+ my ($whitespace) =
+ ($stat_next =~ /^((?:\s*\n[+-])*\s*)/s);
+ my $offset =
+ statement_rawlines($whitespace) - 1;
+
+ $suppress_whiletrailers{$line_nr_next +
+ $offset} = 1;
+ }
+ }
+ if (!defined $suppress_whiletrailers{$linenr} &&
+ $line =~ /\b(?:if|while|for)\s*\(/ && $line !~ /^.\s*#/) {
+ my ($s, $c) = ($stat, $cond);
+
+ if ($c =~ /\bif\s*\(.*[^<>!=]=[^=].*/s) {
+ ERROR("do not use assignment in if condition\n" . $herecurr);
+ }
+
+ # Find out what is on the end of the line after the
+ # conditional.
+ substr($s, 0, length($c), '');
+ $s =~ s/\n.*//g;
+ $s =~ s/$;//g; # Remove any comments
+ if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
+ $c !~ /}\s*while\s*/)
+ {
+ # Find out how long the conditional actually is.
+ my @newlines = ($c =~ /\n/gs);
+ my $cond_lines = 1 + $#newlines;
+ my $stat_real = '';
+
+ $stat_real = raw_line($linenr, $cond_lines)
+ . "\n" if ($cond_lines);
+ if (defined($stat_real) && $cond_lines > 1) {
+ $stat_real = "[...]\n$stat_real";
+ }
+
+ ERROR("trailing statements should be on next line\n" . $herecurr . $stat_real);
+ }
+ }
+
+# Check for bitwise tests written as boolean
+ if ($line =~ /
+ (?:
+ (?:\[|\(|\&\&|\|\|)
+ \s*0[xX][0-9]+\s*
+ (?:\&\&|\|\|)
+ |
+ (?:\&\&|\|\|)
+ \s*0[xX][0-9]+\s*
+ (?:\&\&|\|\||\)|\])
+ )/x)
+ {
+ WARN("boolean test with hexadecimal, perhaps just 1 \& or \|?\n" . $herecurr);
+ }
+
+# if and else should not have general statements after it
+ if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) {
+ my $s = $1;
+ $s =~ s/$;//g; # Remove any comments
+ if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) {
+ ERROR("trailing statements should be on next line\n" . $herecurr);
+ }
+ }
+# if should not continue a brace
+ if ($line =~ /}\s*if\b/) {
+ ERROR("trailing statements should be on next line\n" .
+ $herecurr);
+ }
+# case and default should not have general statements after them
+ if ($line =~ /^.\s*(?:case\s*.*|default\s*):/g &&
+ $line !~ /\G(?:
+ (?:\s*$;*)(?:\s*{)?(?:\s*$;*)(?:\s*\\)?\s*$|
+ \s*return\s+
+ )/xg)
+ {
+ ERROR("trailing statements should be on next line\n" . $herecurr);
+ }
+
+ # Check for }<nl>else {, these must be at the same
+ # indent level to be relevant to each other.
+ if ($prevline=~/}\s*$/ and $line=~/^.\s*else\s*/ and
+ $previndent == $indent) {
+ ERROR("else should follow close brace '}'\n" . $hereprev);
+ }
+
+ if ($prevline=~/}\s*$/ and $line=~/^.\s*while\s*/ and
+ $previndent == $indent) {
+ my ($s, $c) = ctx_statement_block($linenr, $realcnt, 0);
+
+ # Find out what is on the end of the line after the
+ # conditional.
+ substr($s, 0, length($c), '');
+ $s =~ s/\n.*//g;
+
+ if ($s =~ /^\s*;/) {
+ ERROR("while should follow close brace '}'\n" . $hereprev);
+ }
+ }
+
+#studly caps, commented out until figure out how to distinguish between use of existing and adding new
+# if (($line=~/[\w_][a-z\d]+[A-Z]/) and !($line=~/print/)) {
+# print "No studly caps, use _\n";
+# print "$herecurr";
+# $clean = 0;
+# }
+
+#no spaces allowed after \ in define
+ if ($line=~/\#\s*define.*\\\s$/) {
+ WARN("Whitepspace after \\ makes next lines useless\n" . $herecurr);
+ }
+
+#warn if <asm/foo.h> is #included and <linux/foo.h> is available (uses RAW line)
+ if ($tree && $rawline =~ m{^.\s*\#\s*include\s*\<asm\/(.*)\.h\>}) {
+ my $file = "$1.h";
+ my $checkfile = "include/linux/$file";
+ if (-f "$root/$checkfile" &&
+ $realfile ne $checkfile &&
+ $1 !~ /$allowed_asm_includes/)
+ {
+ if ($realfile =~ m{^arch/}) {
+ CHK("Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
+ } else {
+ WARN("Use #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
+ }
+ }
+ }
+
+# multi-statement macros should be enclosed in a do while loop, grab the
+# first statement and ensure its the whole macro if its not enclosed
+# in a known good container
+ if ($realfile !~ m@/vmlinux.lds.h$@ &&
+ $line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
+ my $ln = $linenr;
+ my $cnt = $realcnt;
+ my ($off, $dstat, $dcond, $rest);
+ my $ctx = '';
+
+ my $args = defined($1);
+
+ # Find the end of the macro and limit our statement
+ # search to that.
+ while ($cnt > 0 && defined $lines[$ln - 1] &&
+ $lines[$ln - 1] =~ /^(?:-|..*\\$)/)
+ {
+ $ctx .= $rawlines[$ln - 1] . "\n";
+ $cnt-- if ($lines[$ln - 1] !~ /^-/);
+ $ln++;
+ }
+ $ctx .= $rawlines[$ln - 1];
+
+ ($dstat, $dcond, $ln, $cnt, $off) =
+ ctx_statement_block($linenr, $ln - $linenr + 1, 0);
+ #print "dstat<$dstat> dcond<$dcond> cnt<$cnt> off<$off>\n";
+ #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n";
+
+ # Extract the remainder of the define (if any) and
+ # rip off surrounding spaces, and trailing \'s.
+ $rest = '';
+ while ($off != 0 || ($cnt > 0 && $rest =~ /\\\s*$/)) {
+ #print "ADDING cnt<$cnt> $off <" . substr($lines[$ln - 1], $off) . "> rest<$rest>\n";
+ if ($off != 0 || $lines[$ln - 1] !~ /^-/) {
+ $rest .= substr($lines[$ln - 1], $off) . "\n";
+ $cnt--;
+ }
+ $ln++;
+ $off = 0;
+ }
+ $rest =~ s/\\\n.//g;
+ $rest =~ s/^\s*//s;
+ $rest =~ s/\s*$//s;
+
+ # Clean up the original statement.
+ if ($args) {
+ substr($dstat, 0, length($dcond), '');
+ } else {
+ $dstat =~ s/^.\s*\#\s*define\s+$Ident\s*//;
+ }
+ $dstat =~ s/$;//g;
+ $dstat =~ s/\\\n.//g;
+ $dstat =~ s/^\s*//s;
+ $dstat =~ s/\s*$//s;
+
+ # Flatten any parentheses and braces
+ while ($dstat =~ s/\([^\(\)]*\)/1/ ||
+ $dstat =~ s/\{[^\{\}]*\}/1/ ||
+ $dstat =~ s/\[[^\{\}]*\]/1/)
+ {
+ }
+
+ my $exceptions = qr{
+ $Declare|
+ module_param_named|
+ MODULE_PARAM_DESC|
+ DECLARE_PER_CPU|
+ DEFINE_PER_CPU|
+ __typeof__\(|
+ union|
+ struct|
+ \.$Ident\s*=\s*|
+ ^\"|\"$
+ }x;
+ #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
+ if ($rest ne '' && $rest ne ',') {
+ if ($rest !~ /while\s*\(/ &&
+ $dstat !~ /$exceptions/)
+ {
+ ERROR("Macros with multiple statements should be enclosed in a do - while loop\n" . "$here\n$ctx\n");
+ }
+
+ } elsif ($ctx !~ /;/) {
+ if ($dstat ne '' &&
+ $dstat !~ /^(?:$Ident|-?$Constant)$/ &&
+ $dstat !~ /$exceptions/ &&
+ $dstat !~ /^\.$Ident\s*=/ &&
+ $dstat =~ /$Operators/)
+ {
+ ERROR("Macros with complex values should be enclosed in parenthesis\n" . "$here\n$ctx\n");
+ }
+ }
+ }
+
+# make sure symbols are always wrapped with VMLINUX_SYMBOL() ...
+# all assignments may have only one of the following with an assignment:
+# .
+# ALIGN(...)
+# VMLINUX_SYMBOL(...)
+ if ($realfile eq 'vmlinux.lds.h' && $line =~ /(?:(?:^|\s)$Ident\s*=|=\s*$Ident(?:\s|$))/) {
+ WARN("vmlinux.lds.h needs VMLINUX_SYMBOL() around C-visible symbols\n" . $herecurr);
+ }
+
+# check for redundant bracing round if etc
+ if ($line =~ /(^.*)\bif\b/ && $1 !~ /else\s*$/) {
+ my ($level, $endln, @chunks) =
+ ctx_statement_full($linenr, $realcnt, 1);
+ #print "chunks<$#chunks> linenr<$linenr> endln<$endln> level<$level>\n";
+ #print "APW: <<$chunks[1][0]>><<$chunks[1][1]>>\n";
+ if ($#chunks > 0 && $level == 0) {
+ my $allowed = 0;
+ my $seen = 0;
+ my $herectx = $here . "\n";
+ my $ln = $linenr - 1;
+ for my $chunk (@chunks) {
+ my ($cond, $block) = @{$chunk};
+
+ # If the condition carries leading newlines, then count those as offsets.
+ my ($whitespace) = ($cond =~ /^((?:\s*\n[+-])*\s*)/s);
+ my $offset = statement_rawlines($whitespace) - 1;
+
+ #print "COND<$cond> whitespace<$whitespace> offset<$offset>\n";
+
+ # We have looked at and allowed this specific line.
+ $suppress_ifbraces{$ln + $offset} = 1;
+
+ $herectx .= "$rawlines[$ln + $offset]\n[...]\n";
+ $ln += statement_rawlines($block) - 1;
+
+ substr($block, 0, length($cond), '');
+
+ $seen++ if ($block =~ /^\s*{/);
+
+ #print "cond<$cond> block<$block> allowed<$allowed>\n";
+ if (statement_lines($cond) > 1) {
+ #print "APW: ALLOWED: cond<$cond>\n";
+ $allowed = 1;
+ }
+ if ($block =~/\b(?:if|for|while)\b/) {
+ #print "APW: ALLOWED: block<$block>\n";
+ $allowed = 1;
+ }
+ if (statement_block_size($block) > 1) {
+ #print "APW: ALLOWED: lines block<$block>\n";
+ $allowed = 1;
+ }
+ }
+ if ($seen && !$allowed) {
+ WARN("braces {} are not necessary for any arm of this statement\n" . $herectx);
+ }
+ }
+ }
+ if (!defined $suppress_ifbraces{$linenr - 1} &&
+ $line =~ /\b(if|while|for|else)\b/) {
+ my $allowed = 0;
+
+ # Check the pre-context.
+ if (substr($line, 0, $-[0]) =~ /(\}\s*)$/) {
+ #print "APW: ALLOWED: pre<$1>\n";
+ $allowed = 1;
+ }
+
+ my ($level, $endln, @chunks) =
+ ctx_statement_full($linenr, $realcnt, $-[0]);
+
+ # Check the condition.
+ my ($cond, $block) = @{$chunks[0]};
+ #print "CHECKING<$linenr> cond<$cond> block<$block>\n";
+ if (defined $cond) {
+ substr($block, 0, length($cond), '');
+ }
+ if (statement_lines($cond) > 1) {
+ #print "APW: ALLOWED: cond<$cond>\n";
+ $allowed = 1;
+ }
+ if ($block =~/\b(?:if|for|while)\b/) {
+ #print "APW: ALLOWED: block<$block>\n";
+ $allowed = 1;
+ }
+ if (statement_block_size($block) > 1) {
+ #print "APW: ALLOWED: lines block<$block>\n";
+ $allowed = 1;
+ }
+ # Check the post-context.
+ if (defined $chunks[1]) {
+ my ($cond, $block) = @{$chunks[1]};
+ if (defined $cond) {
+ substr($block, 0, length($cond), '');
+ }
+ if ($block =~ /^\s*\{/) {
+ #print "APW: ALLOWED: chunk-1 block<$block>\n";
+ $allowed = 1;
+ }
+ }
+ if ($level == 0 && $block =~ /^\s*\{/ && !$allowed) {
+ my $herectx = $here . "\n";;
+ my $cnt = statement_rawlines($block);
+
+ for (my $n = 0; $n < $cnt; $n++) {
+ $herectx .= raw_line($linenr, $n) . "\n";;
+ }
+
+ WARN("braces {} are not necessary for single statement blocks\n" . $herectx);
+ }
+ }
+
+# don't include deprecated include files (uses RAW line)
+ for my $inc (@dep_includes) {
+ if ($rawline =~ m@^.\s*\#\s*include\s*\<$inc>@) {
+ ERROR("Don't use <$inc>: see Documentation/feature-removal-schedule.txt\n" . $herecurr);
+ }
+ }
+
+# don't use deprecated functions
+ for my $func (@dep_functions) {
+ if ($line =~ /\b$func\b/) {
+ ERROR("Don't use $func(): see Documentation/feature-removal-schedule.txt\n" . $herecurr);
+ }
+ }
+
+# no volatiles please
+ my $asm_volatile = qr{\b(__asm__|asm)\s+(__volatile__|volatile)\b};
+ if ($line =~ /\bvolatile\b/ && $line !~ /$asm_volatile/) {
+ WARN("Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt\n" . $herecurr);
+ }
+
+# SPIN_LOCK_UNLOCKED & RW_LOCK_UNLOCKED are deprecated
+ if ($line =~ /\b(SPIN_LOCK_UNLOCKED|RW_LOCK_UNLOCKED)/) {
+ ERROR("Use of $1 is deprecated: see Documentation/spinlocks.txt\n" . $herecurr);
+ }
+
+# warn about #if 0
+ if ($line =~ /^.\s*\#\s*if\s+0\b/) {
+ CHK("if this code is redundant consider removing it\n" .
+ $herecurr);
+ }
+
+# check for needless kfree() checks
+ if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
+ my $expr = $1;
+ if ($line =~ /\bkfree\(\Q$expr\E\);/) {
+ WARN("kfree(NULL) is safe this check is probably not required\n" . $hereprev);
+ }
+ }
+# check for needless usb_free_urb() checks
+ if ($prevline =~ /\bif\s*\(([^\)]*)\)/) {
+ my $expr = $1;
+ if ($line =~ /\busb_free_urb\(\Q$expr\E\);/) {
+ WARN("usb_free_urb(NULL) is safe this check is probably not required\n" . $hereprev);
+ }
+ }
+
+# prefer usleep_range over udelay
+ if ($line =~ /\budelay\s*\(\s*(\w+)\s*\)/) {
+ # ignore udelay's < 10, however
+ if (! (($1 =~ /(\d+)/) && ($1 < 10)) ) {
+ CHK("usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $line);
+ }
+ }
+
+# warn about unexpectedly long msleep's
+ if ($line =~ /\bmsleep\s*\((\d+)\);/) {
+ if ($1 < 20) {
+ WARN("msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $line);
+ }
+ }
+
+# warn about #ifdefs in C files
+# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
+# print "#ifdef in C files should be avoided\n";
+# print "$herecurr";
+# $clean = 0;
+# }
+
+# warn about spacing in #ifdefs
+ if ($line =~ /^.\s*\#\s*(ifdef|ifndef|elif)\s\s+/) {
+ ERROR("exactly one space required after that #$1\n" . $herecurr);
+ }
+
+# check for spinlock_t definitions without a comment.
+ if ($line =~ /^.\s*(struct\s+mutex|spinlock_t)\s+\S+;/ ||
+ $line =~ /^.\s*(DEFINE_MUTEX)\s*\(/) {
+ my $which = $1;
+ if (!ctx_has_comment($first_line, $linenr)) {
+ CHK("$1 definition without comment\n" . $herecurr);
+ }
+ }
+# check for memory barriers without a comment.
+ if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
+ if (!ctx_has_comment($first_line, $linenr)) {
+ CHK("memory barrier without comment\n" . $herecurr);
+ }
+ }
+# check of hardware specific defines
+ if ($line =~ m@^.\s*\#\s*if.*\b(__i386__|__powerpc64__|__sun__|__s390x__)\b@ && $realfile !~ m at include/asm-@) {
+ CHK("architecture specific defines should be avoided\n" . $herecurr);
+ }
+
+# Check that the storage class is at the beginning of a declaration
+ if ($line =~ /\b$Storage\b/ && $line !~ /^.\s*$Storage\b/) {
+ WARN("storage class should be at the beginning of the declaration\n" . $herecurr)
+ }
+
+# check the location of the inline attribute, that it is between
+# storage class and type.
+ if ($line =~ /\b$Type\s+$Inline\b/ ||
+ $line =~ /\b$Inline\s+$Storage\b/) {
+ ERROR("inline keyword should sit between storage class and type\n" . $herecurr);
+ }
+
+# Check for __inline__ and __inline, prefer inline
+ if ($line =~ /\b(__inline__|__inline)\b/) {
+ WARN("plain inline is preferred over $1\n" . $herecurr);
+ }
+
+# check for sizeof(&)
+ if ($line =~ /\bsizeof\s*\(\s*\&/) {
+ WARN("sizeof(& should be avoided\n" . $herecurr);
+ }
+
+# check for new externs in .c files.
+ if ($realfile =~ /\.c$/ && defined $stat &&
+ $stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
+ {
+ my $function_name = $1;
+ my $paren_space = $2;
+
+ my $s = $stat;
+ if (defined $cond) {
+ substr($s, 0, length($cond), '');
+ }
+ if ($s =~ /^\s*;/ &&
+ $function_name ne 'uninitialized_var')
+ {
+ WARN("externs should be avoided in .c files\n" . $herecurr);
+ }
+
+ if ($paren_space =~ /\n/) {
+ WARN("arguments for function declarations should follow identifier\n" . $herecurr);
+ }
+
+ } elsif ($realfile =~ /\.c$/ && defined $stat &&
+ $stat =~ /^.\s*extern\s+/)
+ {
+ WARN("externs should be avoided in .c files\n" . $herecurr);
+ }
+
+# checks for new __setup's
+ if ($rawline =~ /\b__setup\("([^"]*)"/) {
+ my $name = $1;
+
+ if (!grep(/$name/, @setup_docs)) {
+ CHK("__setup appears un-documented -- check Documentation/kernel-parameters.txt\n" . $herecurr);
+ }
+ }
+
+# check for pointless casting of kmalloc return
+ if ($line =~ /\*\s*\)\s*k[czm]alloc\b/) {
+ WARN("unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
+ }
+
+# check for gcc specific __FUNCTION__
+ if ($line =~ /__FUNCTION__/) {
+ WARN("__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr);
+ }
+
+# check for semaphores used as mutexes
+ if ($line =~ /^.\s*(DECLARE_MUTEX|init_MUTEX)\s*\(/) {
+ WARN("mutexes are preferred for single holder semaphores\n" . $herecurr);
+ }
+# check for semaphores used as mutexes
+ if ($line =~ /^.\s*init_MUTEX_LOCKED\s*\(/) {
+ WARN("consider using a completion\n" . $herecurr);
+
+ }
+# recommend strict_strto* over simple_strto*
+ if ($line =~ /\bsimple_(strto.*?)\s*\(/) {
+ WARN("consider using strict_$1 in preference to simple_$1\n" . $herecurr);
+ }
+# check for __initcall(), use device_initcall() explicitly please
+ if ($line =~ /^.\s*__initcall\s*\(/) {
+ WARN("please use device_initcall() instead of __initcall()\n" . $herecurr);
+ }
+# check for various ops structs, ensure they are const.
+ my $struct_ops = qr{acpi_dock_ops|
+ address_space_operations|
+ backlight_ops|
+ block_device_operations|
+ dentry_operations|
+ dev_pm_ops|
+ dma_map_ops|
+ extent_io_ops|
+ file_lock_operations|
+ file_operations|
+ hv_ops|
+ ide_dma_ops|
+ intel_dvo_dev_ops|
+ item_operations|
+ iwl_ops|
+ kgdb_arch|
+ kgdb_io|
+ kset_uevent_ops|
+ lock_manager_operations|
+ microcode_ops|
+ mtrr_ops|
+ neigh_ops|
+ nlmsvc_binding|
+ pci_raw_ops|
+ pipe_buf_operations|
+ platform_hibernation_ops|
+ platform_suspend_ops|
+ proto_ops|
+ rpc_pipe_ops|
+ seq_operations|
+ snd_ac97_build_ops|
+ soc_pcmcia_socket_ops|
+ stacktrace_ops|
+ sysfs_ops|
+ tty_operations|
+ usb_mon_operations|
+ wd_ops}x;
+ if ($line !~ /\bconst\b/ &&
+ $line =~ /\bstruct\s+($struct_ops)\b/) {
+ WARN("struct $1 should normally be const\n" .
+ $herecurr);
+ }
+
+# use of NR_CPUS is usually wrong
+# ignore definitions of NR_CPUS and usage to define arrays as likely right
+ if ($line =~ /\bNR_CPUS\b/ &&
+ $line !~ /^.\s*\s*#\s*if\b.*\bNR_CPUS\b/ &&
+ $line !~ /^.\s*\s*#\s*define\b.*\bNR_CPUS\b/ &&
+ $line !~ /^.\s*$Declare\s.*\[[^\]]*NR_CPUS[^\]]*\]/ &&
+ $line !~ /\[[^\]]*\.\.\.[^\]]*NR_CPUS[^\]]*\]/ &&
+ $line !~ /\[[^\]]*NR_CPUS[^\]]*\.\.\.[^\]]*\]/)
+ {
+ WARN("usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
+ }
+
+# check for %L{u,d,i} in strings
+ my $string;
+ while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
+ $string = substr($rawline, $-[1], $+[1] - $-[1]);
+ $string =~ s/%%/__/g;
+ if ($string =~ /(?<!%)%L[udi]/) {
+ WARN("\%Ld/%Lu are not-standard C, use %lld/%llu\n" . $herecurr);
+ last;
+ }
+ }
+
+# whine mightly about in_atomic
+ if ($line =~ /\bin_atomic\s*\(/) {
+ if ($realfile =~ m@^drivers/@) {
+ ERROR("do not use in_atomic in drivers\n" . $herecurr);
+ } elsif ($realfile !~ m@^kernel/@) {
+ WARN("use of in_atomic() is incorrect outside core kernel code\n" . $herecurr);
+ }
+ }
+
+# check for lockdep_set_novalidate_class
+ if ($line =~ /^.\s*lockdep_set_novalidate_class\s*\(/ ||
+ $line =~ /__lockdep_no_validate__\s*\)/ ) {
+ if ($realfile !~ m@^kernel/lockdep@ &&
+ $realfile !~ m@^include/linux/lockdep@ &&
+ $realfile !~ m@^drivers/base/core@) {
+ ERROR("lockdep_no_validate class is reserved for device->mutex.\n" . $herecurr);
+ }
+ }
+ }
+
+ # If we have no input at all, then there is nothing to report on
+ # so just keep quiet.
+ if ($#rawlines == -1) {
+ exit(0);
+ }
+
+ # In mailback mode only produce a report in the negative, for
+ # things that appear to be patches.
+ if ($mailback && ($clean == 1 || !$is_patch)) {
+ exit(0);
+ }
+
+ # This is not a patch, and we are are in 'no-patch' mode so
+ # just keep quiet.
+ if (!$chk_patch && !$is_patch) {
+ exit(0);
+ }
+
+ if (!$is_patch) {
+ ERROR("Does not appear to be a unified-diff format patch\n");
+ }
+ if ($is_patch && $chk_signoff && $signoff == 0) {
+ ERROR("Missing Signed-off-by: line(s)\n");
+ }
+
+ print report_dump();
+ if ($summary && !($clean == 1 && $quiet == 1)) {
+ print "$filename " if ($summary_file);
+ print "total: $cnt_error errors, $cnt_warn warnings, " .
+ (($check)? "$cnt_chk checks, " : "") .
+ "$cnt_lines lines checked\n";
+ print "\n" if ($quiet == 0);
+ }
+
+ if ($quiet == 0) {
+ # If there were whitespace errors which cleanpatch can fix
+ # then suggest that.
+ if ($rpt_cleaners) {
+ print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
+ print " scripts/cleanfile\n\n";
+ }
+ }
+
+ if ($clean == 1 && $quiet == 0) {
+ print "$vname has no obvious style problems and is ready for submission.\n"
+ }
+ if ($clean == 0 && $quiet == 0) {
+ print "$vname has style problems, please review. If any of these errors\n";
+ print "are false positives report them to the maintainer, see\n";
+ print "CHECKPATCH in MAINTAINERS.\n";
+ }
+
+ return $clean;
+}
commit 4c3b5a4891c44ebbc23d80f95e5b66e2ec66b8b1
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Thu Jan 20 20:54:21 2011 +0000
Add scripts directory
Move build and user scripts into scripts directory.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/Makefile b/Makefile
index 6d601ee..eca4c76 100644
--- a/Makefile
+++ b/Makefile
@@ -47,7 +47,7 @@ config-all-devices.mak: $(SUBDIR_DEVICES_MAK)
-include $(SUBDIR_DEVICES_MAK_DEP)
%/config-devices.mak: default-configs/%.mak
- $(call quiet-command,$(SHELL) $(SRC_PATH)/make_device_config.sh $@ $<, " GEN $@")
+ $(call quiet-command,$(SHELL) $(SRC_PATH)/scripts/make_device_config.sh $@ $<, " GEN $@")
@if test -f $@; then \
if cmp -s $@.old $@; then \
mv $@.tmp $@; \
@@ -76,7 +76,7 @@ build-all: $(DOCS) $(TOOLS) recurse-all
config-host.h: config-host.h-timestamp
config-host.h-timestamp: config-host.mak
qemu-options.def: $(SRC_PATH)/qemu-options.hx
- $(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $@")
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
@@ -118,12 +118,12 @@ else
trace.h: trace.h-timestamp
endif
trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak
- $(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -h < $< > $@," GEN trace.h")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -h < $< > $@," GEN trace.h")
@cmp -s $@ trace.h || cp $@ trace.h
trace.c: trace.c-timestamp
trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak
- $(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -c < $< > $@," GEN trace.c")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -c < $< > $@," GEN trace.c")
@cmp -s $@ trace.c || cp $@ trace.c
trace.o: trace.c $(GENERATED_HEADERS)
@@ -136,7 +136,7 @@ trace-dtrace.h: trace-dtrace.dtrace
# rule file. So we use '.dtrace' instead
trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events config-host.mak
- $(call quiet-command,sh $(SRC_PATH)/tracetool --$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace")
@cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace
trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS)
@@ -160,7 +160,7 @@ qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-ob
qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
- $(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $@")
check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o: $(GENERATED_HEADERS)
@@ -282,32 +282,32 @@ TEXIFLAG=$(if $(V),,--quiet)
$(call quiet-command,texi2pdf $(TEXIFLAG) -I . $<," GEN $@")
qemu-options.texi: $(SRC_PATH)/qemu-options.hx
- $(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@," GEN $@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
qemu-monitor.texi: $(SRC_PATH)/hmp-commands.hx
- $(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@," GEN $@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
QMP/qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx
- $(call quiet-command,sh $(SRC_PATH)/hxtool -q < $< > $@," GEN $@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -q < $< > $@," GEN $@")
qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx
- $(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@," GEN $@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi
$(call quiet-command, \
- perl -Ww -- $(SRC_PATH)/texi2pod.pl $< qemu.pod && \
+ perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu.pod && \
pod2man --section=1 --center=" " --release=" " qemu.pod > $@, \
" GEN $@")
qemu-img.1: qemu-img.texi qemu-img-cmds.texi
$(call quiet-command, \
- perl -Ww -- $(SRC_PATH)/texi2pod.pl $< qemu-img.pod && \
+ perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-img.pod && \
pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@, \
" GEN $@")
qemu-nbd.8: qemu-nbd.texi
$(call quiet-command, \
- perl -Ww -- $(SRC_PATH)/texi2pod.pl $< qemu-nbd.pod && \
+ perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-nbd.pod && \
pod2man --section=8 --center=" " --release=" " qemu-nbd.pod > $@, \
" GEN $@")
diff --git a/Makefile.target b/Makefile.target
index e15b1c4..cd2abde 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -52,7 +52,7 @@ TARGET_TYPE=system
endif
$(QEMU_PROG).stp:
- $(call quiet-command,sh $(SRC_PATH)/tracetool \
+ $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool \
--$(TRACE_BACKEND) \
--binary $(bindir)/$(QEMU_PROG) \
--target-arch $(TARGET_ARCH) \
@@ -344,14 +344,14 @@ $(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
$(call LINK,$(obj-y) $(obj-$(TARGET_BASE_ARCH)-y))
-gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/feature_to_c.sh
- $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@")
+gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
+ $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@")
hmp-commands.h: $(SRC_PATH)/hmp-commands.hx
- $(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
qmp-commands.h: $(SRC_PATH)/qmp-commands.hx
- $(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
+ $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
clean:
rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
diff --git a/configure b/configure
index d68f862..210670c 100755
--- a/configure
+++ b/configure
@@ -2266,7 +2266,7 @@ fi
##########################################
# check if trace backend exists
-sh "$source_path/tracetool" "--$trace_backend" --check-backend > /dev/null 2> /dev/null
+sh "$source_path/scripts/tracetool" "--$trace_backend" --check-backend > /dev/null 2> /dev/null
if test "$?" -ne 0 ; then
echo
echo "Error: invalid trace backend"
diff --git a/create_config b/create_config
deleted file mode 100755
index 0098e68..0000000
--- a/create_config
+++ /dev/null
@@ -1,103 +0,0 @@
-#!/bin/sh
-
-echo "/* Automatically generated by create_config - do not modify */"
-
-while read line; do
-
-case $line in
- VERSION=*) # configuration
- version=${line#*=}
- echo "#define QEMU_VERSION \"$version\""
- ;;
- PKGVERSION=*) # configuration
- pkgversion=${line#*=}
- echo "#define QEMU_PKGVERSION \"$pkgversion\""
- ;;
- prefix=* | [a-z]*dir=*) # directory configuration
- name=${line%=*}
- value=${line#*=}
- define_name=`echo $name | tr '[:lower:]' '[:upper:]'`
- eval "define_value=\"$value\""
- echo "#define CONFIG_QEMU_$define_name \"$define_value\""
- # save for the next definitions
- eval "$name=\$define_value"
- ;;
- CONFIG_AUDIO_DRIVERS=*)
- drivers=${line#*=}
- echo "#define CONFIG_AUDIO_DRIVERS \\"
- for drv in $drivers; do
- echo " &${drv}_audio_driver,\\"
- done
- echo ""
- ;;
- CONFIG_BDRV_WHITELIST=*)
- echo "#define CONFIG_BDRV_WHITELIST \\"
- for drv in ${line#*=}; do
- echo " \"${drv}\",\\"
- done
- echo " NULL"
- ;;
- CONFIG_*=y) # configuration
- name=${line%=*}
- echo "#define $name 1"
- ;;
- CONFIG_*=*) # configuration
- name=${line%=*}
- value=${line#*=}
- echo "#define $name $value"
- ;;
- ARCH=*) # configuration
- arch=${line#*=}
- arch_name=`echo $arch | tr '[:lower:]' '[:upper:]'`
- echo "#define HOST_$arch_name 1"
- ;;
- HOST_USB=*)
- # do nothing
- ;;
- HOST_CC=*)
- # do nothing
- ;;
- HOST_*=y) # configuration
- name=${line%=*}
- echo "#define $name 1"
- ;;
- HOST_*=*) # configuration
- name=${line%=*}
- value=${line#*=}
- echo "#define $name $value"
- ;;
- TARGET_ARCH=*) # configuration
- target_arch=${line#*=}
- echo "#define TARGET_ARCH \"$target_arch\""
- ;;
- TARGET_BASE_ARCH=*) # configuration
- target_base_arch=${line#*=}
- if [ "$target_base_arch" != "$target_arch" ]; then
- base_arch_name=`echo $target_base_arch | tr '[:lower:]' '[:upper:]'`
- echo "#define TARGET_$base_arch_name 1"
- fi
- ;;
- TARGET_XML_FILES=*)
- # do nothing
- ;;
- TARGET_ABI_DIR=*)
- # do nothing
- ;;
- TARGET_ARCH2=*)
- # do nothing
- ;;
- TARGET_DIRS=*)
- # do nothing
- ;;
- TARGET_*=y) # configuration
- name=${line%=*}
- echo "#define $name 1"
- ;;
- TARGET_*=*) # configuration
- name=${line%=*}
- value=${line#*=}
- echo "#define $name $value"
- ;;
-esac
-
-done # read
diff --git a/feature_to_c.sh b/feature_to_c.sh
deleted file mode 100644
index 0994d95..0000000
--- a/feature_to_c.sh
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/bin/sh
-
-# Convert text files to compilable C arrays.
-#
-# Copyright (C) 2007 Free Software Foundation, Inc.
-#
-# This file is part of GDB.
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
-
-output=$1
-shift
-
-if test -z "$output" || test -z "$1"; then
- echo "Usage: $0 OUTPUTFILE INPUTFILE..."
- exit 1
-fi
-
-if test -e "$output"; then
- echo "Output file \"$output\" already exists; refusing to overwrite."
- exit 1
-fi
-
-for input; do
- arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'`
-
- ${AWK:-awk} 'BEGIN { n = 0
- print "static const char '$arrayname'[] = {"
- for (i = 0; i < 255; i++)
- _ord_[sprintf("%c", i)] = i
- } {
- split($0, line, "");
- printf " "
- for (i = 1; i <= length($0); i++) {
- c = line[i]
- if (c == "'\''") {
- printf "'\''\\'\'''\'', "
- } else if (c == "\\") {
- printf "'\''\\\\'\'', "
- } else if (_ord_[c] >= 32 && _ord_[c] < 127) {
- printf "'\''%s'\'', ", c
- } else {
- printf "'\''\\%03o'\'', ", _ord_[c]
- }
- if (i % 10 == 0)
- printf "\n "
- }
- printf "'\''\\n'\'', \n"
- } END {
- print " 0 };"
- }' < $input >> $output
-done
-
-echo >> $output
-echo "const char *const xml_builtin[][2] = {" >> $output
-
-for input; do
- basename=`echo $input | sed 's,.*/,,'`
- arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'`
- echo " { \"$basename\", $arrayname }," >> $output
-done
-
-echo " { (char *)0, (char *)0 }" >> $output
-echo "};" >> $output
diff --git a/gdbstub.h b/gdbstub.h
index ce5fdcc..d82334f 100644
--- a/gdbstub.h
+++ b/gdbstub.h
@@ -38,7 +38,7 @@ int gdbserver_start(int);
int gdbserver_start(const char *port);
#endif
-/* in gdbstub-xml.c, generated by feature_to_c.sh */
+/* in gdbstub-xml.c, generated by scripts/feature_to_c.sh */
extern const char *const xml_builtin[][2];
#endif
diff --git a/hxtool b/hxtool
deleted file mode 100644
index 7ca83ed..0000000
--- a/hxtool
+++ /dev/null
@@ -1,102 +0,0 @@
-#!/bin/sh
-
-hxtoh()
-{
- flag=1
- while read -r str; do
- case $str in
- HXCOMM*)
- ;;
- STEXI*|ETEXI*|SQMP*|EQMP*) flag=$(($flag^1))
- ;;
- *)
- test $flag -eq 1 && printf "%s\n" "$str"
- ;;
- esac
- done
-}
-
-hxtotexi()
-{
- flag=0
- line=1
- while read -r str; do
- case "$str" in
- HXCOMM*)
- ;;
- STEXI*)
- if test $flag -eq 1 ; then
- echo "line $line: syntax error: expected ETEXI, found $str" >&2
- exit 1
- fi
- flag=1
- ;;
- ETEXI*)
- if test $flag -ne 1 ; then
- echo "line $line: syntax error: expected STEXI, found $str" >&2
- exit 1
- fi
- flag=0
- ;;
- SQMP*|EQMP*)
- if test $flag -eq 1 ; then
- echo "line $line: syntax error: expected ETEXI, found $str" >&2
- exit 1
- fi
- ;;
- DEFHEADING*)
- echo "$(expr "$str" : "DEFHEADING(\(.*\))")"
- ;;
- *)
- test $flag -eq 1 && echo "$str"
- ;;
- esac
- line=$((line+1))
- done
-}
-
-hxtoqmp()
-{
- IFS=
- flag=0
- line=1
- while read -r str; do
- case "$str" in
- HXCOMM*)
- ;;
- SQMP*)
- if test $flag -eq 1 ; then
- echo "line $line: syntax error: expected EQMP, found $str" >&2
- exit 1
- fi
- flag=1
- ;;
- EQMP*)
- if test $flag -ne 1 ; then
- echo "line $line: syntax error: expected SQMP, found $str" >&2
- exit 1
- fi
- flag=0
- ;;
- STEXI*|ETEXI*)
- if test $flag -eq 1 ; then
- echo "line $line: syntax error: expected EQMP, found $str" >&2
- exit 1
- fi
- ;;
- *)
- test $flag -eq 1 && echo "$str"
- ;;
- esac
- line=$((line+1))
- done
-}
-
-case "$1" in
-"-h") hxtoh ;;
-"-t") hxtotexi ;;
-"-q") hxtoqmp ;;
-*) exit 1 ;;
-esac
-
-exit 0
diff --git a/make_device_config.sh b/make_device_config.sh
deleted file mode 100644
index 5d14885..0000000
--- a/make_device_config.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#! /bin/sh
-# Construct a target device config file from a default, pulling in any
-# files from include directives.
-
-dest=$1.tmp
-dep=$1.d
-src=$2
-src_dir=`dirname $src`
-all_includes=
-
-process_includes () {
- cat $1 | grep '^include' | \
- while read include file ; do
- all_includes="$all_includes $src_dir/$file"
- process_includes $src_dir/$file
- done
-}
-
-f=$src
-while [ -n "$f" ] ; do
- f=`tr -d '\r' < $f | awk '/^include / {printf "'$src_dir'/%s", $2}'`
- [ $? = 0 ] || exit 1
- all_includes="$all_includes $f"
-done
-process_includes $src > $dest
-
-cat $src $all_includes | grep -v '^include' > $dest
-echo "$1: $all_includes" > $dep
diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile
index b4be31e..51da288 100644
--- a/pc-bios/optionrom/Makefile
+++ b/pc-bios/optionrom/Makefile
@@ -23,7 +23,7 @@ build-all: multiboot.bin linuxboot.bin
$(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@," Building $(TARGET_DIR)$@")
%.bin: %.raw
- $(call quiet-command,$(SHELL) $(SRC_PATH)/pc-bios/optionrom/signrom.sh $< $@," Signing $(TARGET_DIR)$@")
+ $(call quiet-command,$(SHELL) $(SRC_PATH)/scripts/signrom.sh $< $@," Signing $(TARGET_DIR)$@")
clean:
rm -f *.o *.d *.raw *.img *.bin *~
diff --git a/pc-bios/optionrom/signrom.sh b/pc-bios/optionrom/signrom.sh
deleted file mode 100755
index 9dc5c63..0000000
--- a/pc-bios/optionrom/signrom.sh
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/bin/sh
-
-# Option ROM Signing utility
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
-#
-# Copyright Novell Inc, 2009
-# Authors: Alexander Graf <agraf at suse.de>
-#
-# Syntax: signrom.sh <input> <output>
-
-# did we get proper arguments?
-test "$1" -a "$2" || exit 1
-
-sum=0
-
-# find out the file size
-x=`dd if="$1" bs=1 count=1 skip=2 2>/dev/null | od -t u1 -A n`
-#size=`expr $x \* 512 - 1`
-size=$(( $x * 512 - 1 ))
-
-# now get the checksum
-nums=`od -A n -t u1 -v -N $size "$1"`
-for i in ${nums}; do
- # add each byte's value to sum
- sum=`expr \( $sum + $i \) % 256`
-done
-
-sum=$(( (256 - $sum) % 256 ))
-sum_octal=$( printf "%o" $sum )
-
-# and write the output file
-cp "$1" "$2"
-printf "\\$sum_octal" | dd of="$2" bs=1 count=1 seek=$size conv=notrunc 2>/dev/null
diff --git a/qemu-binfmt-conf.sh b/qemu-binfmt-conf.sh
deleted file mode 100644
index c50beb7..0000000
--- a/qemu-binfmt-conf.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/bin/sh
-# enable automatic i386/ARM/M68K/MIPS/SPARC/PPC program execution by the kernel
-
-# load the binfmt_misc module
-if [ ! -d /proc/sys/fs/binfmt_misc ]; then
- /sbin/modprobe binfmt_misc
-fi
-if [ ! -f /proc/sys/fs/binfmt_misc/register ]; then
- mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
-fi
-
-# probe cpu type
-cpu=`uname -m`
-case "$cpu" in
- i386|i486|i586|i686|i86pc|BePC|x86_64)
- cpu="i386"
- ;;
- m68k)
- cpu="m68k"
- ;;
- mips*)
- cpu="mips"
- ;;
- "Power Macintosh"|ppc|ppc64)
- cpu="ppc"
- ;;
- armv[4-9]*)
- cpu="arm"
- ;;
-esac
-
-# register the interpreter for each cpu except for the native one
-if [ $cpu != "i386" ] ; then
- echo ':i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register
- echo ':i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register
-fi
-if [ $cpu != "alpha" ] ; then
- echo ':alpha:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x26\x90:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-alpha:' > /proc/sys/fs/binfmt_misc/register
-fi
-if [ $cpu != "arm" ] ; then
- echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-arm:' > /proc/sys/fs/binfmt_misc/register
- echo ':armeb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-armeb:' > /proc/sys/fs/binfmt_misc/register
-fi
-if [ $cpu != "sparc" ] ; then
- echo ':sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-sparc:' > /proc/sys/fs/binfmt_misc/register
-fi
-if [ $cpu != "ppc" ] ; then
- echo ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-ppc:' > /proc/sys/fs/binfmt_misc/register
-fi
-if [ $cpu != "m68k" ] ; then
- echo 'Please check cpu value and header information for m68k!'
- echo ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-m68k:' > /proc/sys/fs/binfmt_misc/register
-fi
-if [ $cpu != "mips" ] ; then
- # FIXME: We could use the other endianness on a MIPS host.
- echo ':mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips:' > /proc/sys/fs/binfmt_misc/register
- echo ':mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mipsel:' > /proc/sys/fs/binfmt_misc/register
- echo ':mipsn32:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mipsn32:' > /proc/sys/fs/binfmt_misc/register
- echo ':mipsn32el:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mipsn32el:' > /proc/sys/fs/binfmt_misc/register
- echo ':mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips64:' > /proc/sys/fs/binfmt_misc/register
- echo ':mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mips64el:' > /proc/sys/fs/binfmt_misc/register
-fi
-if [ $cpu != "sh" ] ; then
- echo ':sh4:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-sh4:' > /proc/sys/fs/binfmt_misc/register
- echo ':sh4eb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-sh4eb:' > /proc/sys/fs/binfmt_misc/register
-fi
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 45190f6..22a8663 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -2132,7 +2132,7 @@ Then you can launch the precompiled @file{ls} x86 executable:
@example
qemu-i386 tests/i386/ls
@end example
-You can look at @file{qemu-binfmt-conf.sh} so that
+You can look at @file{scripts/qemu-binfmt-conf.sh} so that
QEMU is automatically launched by the Linux kernel when you try to
launch x86 executables. It requires the @code{binfmt_misc} module in the
Linux kernel.
diff --git a/rules.mak b/rules.mak
index 738eec3..ed59c9e 100644
--- a/rules.mak
+++ b/rules.mak
@@ -57,7 +57,7 @@ find-in-path = $(if $(find-string /, $1), \
@test -f $@ || cp $< $@
%.h-timestamp: %.mak
- $(call quiet-command, sh $(SRC_PATH)/create_config < $< > $@, " GEN $*.h")
+ $(call quiet-command, sh $(SRC_PATH)/scripts/create_config < $< > $@, " GEN $*.h")
@cmp $@ $*.h >/dev/null 2>&1 || cp $@ $*.h
# will delete the target of a rule if commands exit with a nonzero exit status
diff --git a/scripts/create_config b/scripts/create_config
new file mode 100755
index 0000000..0098e68
--- /dev/null
+++ b/scripts/create_config
@@ -0,0 +1,103 @@
+#!/bin/sh
+
+echo "/* Automatically generated by create_config - do not modify */"
+
+while read line; do
+
+case $line in
+ VERSION=*) # configuration
+ version=${line#*=}
+ echo "#define QEMU_VERSION \"$version\""
+ ;;
+ PKGVERSION=*) # configuration
+ pkgversion=${line#*=}
+ echo "#define QEMU_PKGVERSION \"$pkgversion\""
+ ;;
+ prefix=* | [a-z]*dir=*) # directory configuration
+ name=${line%=*}
+ value=${line#*=}
+ define_name=`echo $name | tr '[:lower:]' '[:upper:]'`
+ eval "define_value=\"$value\""
+ echo "#define CONFIG_QEMU_$define_name \"$define_value\""
+ # save for the next definitions
+ eval "$name=\$define_value"
+ ;;
+ CONFIG_AUDIO_DRIVERS=*)
+ drivers=${line#*=}
+ echo "#define CONFIG_AUDIO_DRIVERS \\"
+ for drv in $drivers; do
+ echo " &${drv}_audio_driver,\\"
+ done
+ echo ""
+ ;;
+ CONFIG_BDRV_WHITELIST=*)
+ echo "#define CONFIG_BDRV_WHITELIST \\"
+ for drv in ${line#*=}; do
+ echo " \"${drv}\",\\"
+ done
+ echo " NULL"
+ ;;
+ CONFIG_*=y) # configuration
+ name=${line%=*}
+ echo "#define $name 1"
+ ;;
+ CONFIG_*=*) # configuration
+ name=${line%=*}
+ value=${line#*=}
+ echo "#define $name $value"
+ ;;
+ ARCH=*) # configuration
+ arch=${line#*=}
+ arch_name=`echo $arch | tr '[:lower:]' '[:upper:]'`
+ echo "#define HOST_$arch_name 1"
+ ;;
+ HOST_USB=*)
+ # do nothing
+ ;;
+ HOST_CC=*)
+ # do nothing
+ ;;
+ HOST_*=y) # configuration
+ name=${line%=*}
+ echo "#define $name 1"
+ ;;
+ HOST_*=*) # configuration
+ name=${line%=*}
+ value=${line#*=}
+ echo "#define $name $value"
+ ;;
+ TARGET_ARCH=*) # configuration
+ target_arch=${line#*=}
+ echo "#define TARGET_ARCH \"$target_arch\""
+ ;;
+ TARGET_BASE_ARCH=*) # configuration
+ target_base_arch=${line#*=}
+ if [ "$target_base_arch" != "$target_arch" ]; then
+ base_arch_name=`echo $target_base_arch | tr '[:lower:]' '[:upper:]'`
+ echo "#define TARGET_$base_arch_name 1"
+ fi
+ ;;
+ TARGET_XML_FILES=*)
+ # do nothing
+ ;;
+ TARGET_ABI_DIR=*)
+ # do nothing
+ ;;
+ TARGET_ARCH2=*)
+ # do nothing
+ ;;
+ TARGET_DIRS=*)
+ # do nothing
+ ;;
+ TARGET_*=y) # configuration
+ name=${line%=*}
+ echo "#define $name 1"
+ ;;
+ TARGET_*=*) # configuration
+ name=${line%=*}
+ value=${line#*=}
+ echo "#define $name $value"
+ ;;
+esac
+
+done # read
diff --git a/scripts/feature_to_c.sh b/scripts/feature_to_c.sh
new file mode 100644
index 0000000..0994d95
--- /dev/null
+++ b/scripts/feature_to_c.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+# Convert text files to compilable C arrays.
+#
+# Copyright (C) 2007 Free Software Foundation, Inc.
+#
+# This file is part of GDB.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+output=$1
+shift
+
+if test -z "$output" || test -z "$1"; then
+ echo "Usage: $0 OUTPUTFILE INPUTFILE..."
+ exit 1
+fi
+
+if test -e "$output"; then
+ echo "Output file \"$output\" already exists; refusing to overwrite."
+ exit 1
+fi
+
+for input; do
+ arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'`
+
+ ${AWK:-awk} 'BEGIN { n = 0
+ print "static const char '$arrayname'[] = {"
+ for (i = 0; i < 255; i++)
+ _ord_[sprintf("%c", i)] = i
+ } {
+ split($0, line, "");
+ printf " "
+ for (i = 1; i <= length($0); i++) {
+ c = line[i]
+ if (c == "'\''") {
+ printf "'\''\\'\'''\'', "
+ } else if (c == "\\") {
+ printf "'\''\\\\'\'', "
+ } else if (_ord_[c] >= 32 && _ord_[c] < 127) {
+ printf "'\''%s'\'', ", c
+ } else {
+ printf "'\''\\%03o'\'', ", _ord_[c]
+ }
+ if (i % 10 == 0)
+ printf "\n "
+ }
+ printf "'\''\\n'\'', \n"
+ } END {
+ print " 0 };"
+ }' < $input >> $output
+done
+
+echo >> $output
+echo "const char *const xml_builtin[][2] = {" >> $output
+
+for input; do
+ basename=`echo $input | sed 's,.*/,,'`
+ arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'`
+ echo " { \"$basename\", $arrayname }," >> $output
+done
+
+echo " { (char *)0, (char *)0 }" >> $output
+echo "};" >> $output
diff --git a/scripts/hxtool b/scripts/hxtool
new file mode 100644
index 0000000..7ca83ed
--- /dev/null
+++ b/scripts/hxtool
@@ -0,0 +1,102 @@
+#!/bin/sh
+
+hxtoh()
+{
+ flag=1
+ while read -r str; do
+ case $str in
+ HXCOMM*)
+ ;;
+ STEXI*|ETEXI*|SQMP*|EQMP*) flag=$(($flag^1))
+ ;;
+ *)
+ test $flag -eq 1 && printf "%s\n" "$str"
+ ;;
+ esac
+ done
+}
+
+hxtotexi()
+{
+ flag=0
+ line=1
+ while read -r str; do
+ case "$str" in
+ HXCOMM*)
+ ;;
+ STEXI*)
+ if test $flag -eq 1 ; then
+ echo "line $line: syntax error: expected ETEXI, found $str" >&2
+ exit 1
+ fi
+ flag=1
+ ;;
+ ETEXI*)
+ if test $flag -ne 1 ; then
+ echo "line $line: syntax error: expected STEXI, found $str" >&2
+ exit 1
+ fi
+ flag=0
+ ;;
+ SQMP*|EQMP*)
+ if test $flag -eq 1 ; then
+ echo "line $line: syntax error: expected ETEXI, found $str" >&2
+ exit 1
+ fi
+ ;;
+ DEFHEADING*)
+ echo "$(expr "$str" : "DEFHEADING(\(.*\))")"
+ ;;
+ *)
+ test $flag -eq 1 && echo "$str"
+ ;;
+ esac
+ line=$((line+1))
+ done
+}
+
+hxtoqmp()
+{
+ IFS=
+ flag=0
+ line=1
+ while read -r str; do
+ case "$str" in
+ HXCOMM*)
+ ;;
+ SQMP*)
+ if test $flag -eq 1 ; then
+ echo "line $line: syntax error: expected EQMP, found $str" >&2
+ exit 1
+ fi
+ flag=1
+ ;;
+ EQMP*)
+ if test $flag -ne 1 ; then
+ echo "line $line: syntax error: expected SQMP, found $str" >&2
+ exit 1
+ fi
+ flag=0
+ ;;
+ STEXI*|ETEXI*)
+ if test $flag -eq 1 ; then
+ echo "line $line: syntax error: expected EQMP, found $str" >&2
+ exit 1
+ fi
+ ;;
+ *)
+ test $flag -eq 1 && echo "$str"
+ ;;
+ esac
+ line=$((line+1))
+ done
+}
+
+case "$1" in
+"-h") hxtoh ;;
+"-t") hxtotexi ;;
+"-q") hxtoqmp ;;
+*) exit 1 ;;
+esac
+
+exit 0
diff --git a/scripts/make_device_config.sh b/scripts/make_device_config.sh
new file mode 100644
index 0000000..5d14885
--- /dev/null
+++ b/scripts/make_device_config.sh
@@ -0,0 +1,28 @@
+#! /bin/sh
+# Construct a target device config file from a default, pulling in any
+# files from include directives.
+
+dest=$1.tmp
+dep=$1.d
+src=$2
+src_dir=`dirname $src`
+all_includes=
+
+process_includes () {
+ cat $1 | grep '^include' | \
+ while read include file ; do
+ all_includes="$all_includes $src_dir/$file"
+ process_includes $src_dir/$file
+ done
+}
+
+f=$src
+while [ -n "$f" ] ; do
+ f=`tr -d '\r' < $f | awk '/^include / {printf "'$src_dir'/%s", $2}'`
+ [ $? = 0 ] || exit 1
+ all_includes="$all_includes $f"
+done
+process_includes $src > $dest
+
+cat $src $all_includes | grep -v '^include' > $dest
+echo "$1: $all_includes" > $dep
diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh
new file mode 100644
index 0000000..c50beb7
--- /dev/null
+++ b/scripts/qemu-binfmt-conf.sh
@@ -0,0 +1,66 @@
+#!/bin/sh
+# enable automatic i386/ARM/M68K/MIPS/SPARC/PPC program execution by the kernel
+
+# load the binfmt_misc module
+if [ ! -d /proc/sys/fs/binfmt_misc ]; then
+ /sbin/modprobe binfmt_misc
+fi
+if [ ! -f /proc/sys/fs/binfmt_misc/register ]; then
+ mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
+fi
+
+# probe cpu type
+cpu=`uname -m`
+case "$cpu" in
+ i386|i486|i586|i686|i86pc|BePC|x86_64)
+ cpu="i386"
+ ;;
+ m68k)
+ cpu="m68k"
+ ;;
+ mips*)
+ cpu="mips"
+ ;;
+ "Power Macintosh"|ppc|ppc64)
+ cpu="ppc"
+ ;;
+ armv[4-9]*)
+ cpu="arm"
+ ;;
+esac
+
+# register the interpreter for each cpu except for the native one
+if [ $cpu != "i386" ] ; then
+ echo ':i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register
+ echo ':i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register
+fi
+if [ $cpu != "alpha" ] ; then
+ echo ':alpha:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x26\x90:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-alpha:' > /proc/sys/fs/binfmt_misc/register
+fi
+if [ $cpu != "arm" ] ; then
+ echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-arm:' > /proc/sys/fs/binfmt_misc/register
+ echo ':armeb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-armeb:' > /proc/sys/fs/binfmt_misc/register
+fi
+if [ $cpu != "sparc" ] ; then
+ echo ':sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-sparc:' > /proc/sys/fs/binfmt_misc/register
+fi
+if [ $cpu != "ppc" ] ; then
+ echo ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-ppc:' > /proc/sys/fs/binfmt_misc/register
+fi
+if [ $cpu != "m68k" ] ; then
+ echo 'Please check cpu value and header information for m68k!'
+ echo ':m68k:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x04:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-m68k:' > /proc/sys/fs/binfmt_misc/register
+fi
+if [ $cpu != "mips" ] ; then
+ # FIXME: We could use the other endianness on a MIPS host.
+ echo ':mips:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips:' > /proc/sys/fs/binfmt_misc/register
+ echo ':mipsel:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mipsel:' > /proc/sys/fs/binfmt_misc/register
+ echo ':mipsn32:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mipsn32:' > /proc/sys/fs/binfmt_misc/register
+ echo ':mipsn32el:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mipsn32el:' > /proc/sys/fs/binfmt_misc/register
+ echo ':mips64:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-mips64:' > /proc/sys/fs/binfmt_misc/register
+ echo ':mips64el:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x08\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-mips64el:' > /proc/sys/fs/binfmt_misc/register
+fi
+if [ $cpu != "sh" ] ; then
+ echo ':sh4:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-sh4:' > /proc/sys/fs/binfmt_misc/register
+ echo ':sh4eb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-sh4eb:' > /proc/sys/fs/binfmt_misc/register
+fi
diff --git a/scripts/signrom.sh b/scripts/signrom.sh
new file mode 100755
index 0000000..9dc5c63
--- /dev/null
+++ b/scripts/signrom.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+# Option ROM Signing utility
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# Copyright Novell Inc, 2009
+# Authors: Alexander Graf <agraf at suse.de>
+#
+# Syntax: signrom.sh <input> <output>
+
+# did we get proper arguments?
+test "$1" -a "$2" || exit 1
+
+sum=0
+
+# find out the file size
+x=`dd if="$1" bs=1 count=1 skip=2 2>/dev/null | od -t u1 -A n`
+#size=`expr $x \* 512 - 1`
+size=$(( $x * 512 - 1 ))
+
+# now get the checksum
+nums=`od -A n -t u1 -v -N $size "$1"`
+for i in ${nums}; do
+ # add each byte's value to sum
+ sum=`expr \( $sum + $i \) % 256`
+done
+
+sum=$(( (256 - $sum) % 256 ))
+sum_octal=$( printf "%o" $sum )
+
+# and write the output file
+cp "$1" "$2"
+printf "\\$sum_octal" | dd of="$2" bs=1 count=1 seek=$size conv=notrunc 2>/dev/null
diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py
new file mode 100755
index 0000000..553a727
--- /dev/null
+++ b/scripts/simpletrace.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+#
+# Pretty-printer for simple trace backend binary trace files
+#
+# Copyright IBM, Corp. 2010
+#
+# This work is licensed under the terms of the GNU GPL, version 2. See
+# the COPYING file in the top-level directory.
+#
+# For help see docs/tracing.txt
+
+import sys
+import struct
+import re
+
+header_event_id = 0xffffffffffffffff
+header_magic = 0xf2b177cb0aa429b4
+header_version = 0
+
+trace_fmt = '=QQQQQQQQ'
+trace_len = struct.calcsize(trace_fmt)
+event_re = re.compile(r'(disable\s+)?([a-zA-Z0-9_]+)\(([^)]*)\).*')
+
+def err(msg):
+ sys.stderr.write(msg + '\n')
+ sys.exit(1)
+
+def parse_events(fobj):
+ """Parse a trace-events file."""
+
+ def get_argnames(args):
+ """Extract argument names from a parameter list."""
+ return tuple(arg.split()[-1].lstrip('*') for arg in args.split(','))
+
+ events = {}
+ event_num = 0
+ for line in fobj:
+ m = event_re.match(line.strip())
+ if m is None:
+ continue
+
+ disable, name, args = m.groups()
+ events[event_num] = (name,) + get_argnames(args)
+ event_num += 1
+ return events
+
+def read_record(fobj):
+ """Deserialize a trace record from a file."""
+ s = fobj.read(trace_len)
+ if len(s) != trace_len:
+ return None
+ return struct.unpack(trace_fmt, s)
+
+def read_trace_file(fobj):
+ """Deserialize trace records from a file."""
+ header = read_record(fobj)
+ if header is None or \
+ header[0] != header_event_id or \
+ header[1] != header_magic or \
+ header[2] != header_version:
+ err('not a trace file or incompatible version')
+
+ while True:
+ rec = read_record(fobj)
+ if rec is None:
+ break
+
+ yield rec
+
+class Formatter(object):
+ def __init__(self, events):
+ self.events = events
+ self.last_timestamp = None
+
+ def format_record(self, rec):
+ if self.last_timestamp is None:
+ self.last_timestamp = rec[1]
+ delta_ns = rec[1] - self.last_timestamp
+ self.last_timestamp = rec[1]
+
+ event = self.events[rec[0]]
+ fields = [event[0], '%0.3f' % (delta_ns / 1000.0)]
+ for i in xrange(1, len(event)):
+ fields.append('%s=0x%x' % (event[i], rec[i + 1]))
+ return ' '.join(fields)
+
+if len(sys.argv) != 3:
+ err('usage: %s <trace-events> <trace-file>' % sys.argv[0])
+
+events = parse_events(open(sys.argv[1], 'r'))
+formatter = Formatter(events)
+for rec in read_trace_file(open(sys.argv[2], 'rb')):
+ print formatter.format_record(rec)
diff --git a/scripts/texi2pod.pl b/scripts/texi2pod.pl
new file mode 100755
index 0000000..9ed056a
--- /dev/null
+++ b/scripts/texi2pod.pl
@@ -0,0 +1,477 @@
+#! /usr/bin/perl -w
+
+# Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+
+# This file is part of GCC.
+
+# GCC 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, or (at your option)
+# any later version.
+
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING. If not,
+# see <http://www.gnu.org/licenses/>.
+
+# This does trivial (and I mean _trivial_) conversion of Texinfo
+# markup to Perl POD format. It's intended to be used to extract
+# something suitable for a manpage from a Texinfo document.
+
+$output = 0;
+$skipping = 0;
+%sects = ();
+$section = "";
+ at icstack = ();
+ at endwstack = ();
+ at skstack = ();
+ at instack = ();
+$shift = "";
+%defs = ();
+$fnno = 1;
+$inf = "";
+$ibase = "";
+ at ipath = ();
+
+while ($_ = shift) {
+ if (/^-D(.*)$/) {
+ if ($1 ne "") {
+ $flag = $1;
+ } else {
+ $flag = shift;
+ }
+ $value = "";
+ ($flag, $value) = ($flag =~ /^([^=]+)(?:=(.+))?/);
+ die "no flag specified for -D\n"
+ unless $flag ne "";
+ die "flags may only contain letters, digits, hyphens, dashes and underscores\n"
+ unless $flag =~ /^[a-zA-Z0-9_-]+$/;
+ $defs{$flag} = $value;
+ } elsif (/^-I(.*)$/) {
+ if ($1 ne "") {
+ $flag = $1;
+ } else {
+ $flag = shift;
+ }
+ push (@ipath, $flag);
+ } elsif (/^-/) {
+ usage();
+ } else {
+ $in = $_, next unless defined $in;
+ $out = $_, next unless defined $out;
+ usage();
+ }
+}
+
+if (defined $in) {
+ $inf = gensym();
+ open($inf, "<$in") or die "opening \"$in\": $!\n";
+ $ibase = $1 if $in =~ m|^(.+)/[^/]+$|;
+} else {
+ $inf = \*STDIN;
+}
+
+if (defined $out) {
+ open(STDOUT, ">$out") or die "opening \"$out\": $!\n";
+}
+
+while(defined $inf) {
+while(<$inf>) {
+ # Certain commands are discarded without further processing.
+ /^\@(?:
+ [a-z]+index # @*index: useful only in complete manual
+ |need # @need: useful only in printed manual
+ |(?:end\s+)?group # @group .. @end group: ditto
+ |page # @page: ditto
+ |node # @node: useful only in .info file
+ |(?:end\s+)?ifnottex # @ifnottex .. @end ifnottex: use contents
+ )\b/x and next;
+
+ chomp;
+
+ # Look for filename and title markers.
+ /^\@setfilename\s+([^.]+)/ and $fn = $1, next;
+ /^\@settitle\s+([^.]+)/ and $tl = postprocess($1), next;
+
+ # Identify a man title but keep only the one we are interested in.
+ /^\@c\s+man\s+title\s+([A-Za-z0-9-]+)\s+(.+)/ and do {
+ if (exists $defs{$1}) {
+ $fn = $1;
+ $tl = postprocess($2);
+ }
+ next;
+ };
+
+ # Look for blocks surrounded by @c man begin SECTION ... @c man end.
+ # This really oughta be @ifman ... @end ifman and the like, but such
+ # would require rev'ing all other Texinfo translators.
+ /^\@c\s+man\s+begin\s+([A-Z]+)\s+([A-Za-z0-9-]+)/ and do {
+ $output = 1 if exists $defs{$2};
+ $sect = $1;
+ next;
+ };
+ /^\@c\s+man\s+begin\s+([A-Z]+)/ and $sect = $1, $output = 1, next;
+ /^\@c\s+man\s+end/ and do {
+ $sects{$sect} = "" unless exists $sects{$sect};
+ $sects{$sect} .= postprocess($section);
+ $section = "";
+ $output = 0;
+ next;
+ };
+
+ # handle variables
+ /^\@set\s+([a-zA-Z0-9_-]+)\s*(.*)$/ and do {
+ $defs{$1} = $2;
+ next;
+ };
+ /^\@clear\s+([a-zA-Z0-9_-]+)/ and do {
+ delete $defs{$1};
+ next;
+ };
+
+ next unless $output;
+
+ # Discard comments. (Can't do it above, because then we'd never see
+ # @c man lines.)
+ /^\@c\b/ and next;
+
+ # End-block handler goes up here because it needs to operate even
+ # if we are skipping.
+ /^\@end\s+([a-z]+)/ and do {
+ # Ignore @end foo, where foo is not an operation which may
+ # cause us to skip, if we are presently skipping.
+ my $ended = $1;
+ next if $skipping && $ended !~ /^(?:ifset|ifclear|ignore|menu|iftex|copying)$/;
+
+ die "\@end $ended without \@$ended at line $.\n" unless defined $endw;
+ die "\@$endw ended by \@end $ended at line $.\n" unless $ended eq $endw;
+
+ $endw = pop @endwstack;
+
+ if ($ended =~ /^(?:ifset|ifclear|ignore|menu|iftex)$/) {
+ $skipping = pop @skstack;
+ next;
+ } elsif ($ended =~ /^(?:example|smallexample|display)$/) {
+ $shift = "";
+ $_ = ""; # need a paragraph break
+ } elsif ($ended =~ /^(?:itemize|enumerate|[fv]?table)$/) {
+ $_ = "\n=back\n";
+ $ic = pop @icstack;
+ } elsif ($ended eq "multitable") {
+ $_ = "\n=back\n";
+ } else {
+ die "unknown command \@end $ended at line $.\n";
+ }
+ };
+
+ # We must handle commands which can cause skipping even while we
+ # are skipping, otherwise we will not process nested conditionals
+ # correctly.
+ /^\@ifset\s+([a-zA-Z0-9_-]+)/ and do {
+ push @endwstack, $endw;
+ push @skstack, $skipping;
+ $endw = "ifset";
+ $skipping = 1 unless exists $defs{$1};
+ next;
+ };
+
+ /^\@ifclear\s+([a-zA-Z0-9_-]+)/ and do {
+ push @endwstack, $endw;
+ push @skstack, $skipping;
+ $endw = "ifclear";
+ $skipping = 1 if exists $defs{$1};
+ next;
+ };
+
+ /^\@(ignore|menu|iftex|copying)\b/ and do {
+ push @endwstack, $endw;
+ push @skstack, $skipping;
+ $endw = $1;
+ $skipping = 1;
+ next;
+ };
+
+ next if $skipping;
+
+ # Character entities. First the ones that can be replaced by raw text
+ # or discarded outright:
+ s/\@copyright\{\}/(c)/g;
+ s/\@dots\{\}/.../g;
+ s/\@enddots\{\}/..../g;
+ s/\@([.!? ])/$1/g;
+ s/\@[:-]//g;
+ s/\@bullet(?:\{\})?/*/g;
+ s/\@TeX\{\}/TeX/g;
+ s/\@pounds\{\}/\#/g;
+ s/\@minus(?:\{\})?/-/g;
+ s/\\,/,/g;
+
+ # Now the ones that have to be replaced by special escapes
+ # (which will be turned back into text by unmunge())
+ s/&/&/g;
+ s/\@\{/{/g;
+ s/\@\}/}/g;
+ s/\@\@/&at;/g;
+
+ # Inside a verbatim block, handle @var specially.
+ if ($shift ne "") {
+ s/\@var\{([^\}]*)\}/<$1>/g;
+ }
+
+ # POD doesn't interpret E<> inside a verbatim block.
+ if ($shift eq "") {
+ s/</</g;
+ s/>/>/g;
+ } else {
+ s/</</g;
+ s/>/>/g;
+ }
+
+ # Single line command handlers.
+
+ /^\@include\s+(.+)$/ and do {
+ push @instack, $inf;
+ $inf = gensym();
+ $file = postprocess($1);
+
+ # Try cwd and $ibase, then explicit -I paths.
+ $done = 0;
+ foreach $path ("", $ibase, @ipath) {
+ $mypath = $file;
+ $mypath = $path . "/" . $mypath if ($path ne "");
+ open($inf, "<" . $mypath) and ($done = 1, last);
+ }
+ die "cannot find $file" if !$done;
+ next;
+ };
+
+ /^\@(?:section|unnumbered|unnumberedsec|center)\s+(.+)$/
+ and $_ = "\n=head2 $1\n";
+ /^\@subsection\s+(.+)$/
+ and $_ = "\n=head3 $1\n";
+ /^\@subsubsection\s+(.+)$/
+ and $_ = "\n=head4 $1\n";
+
+ # Block command handlers:
+ /^\@itemize(?:\s+(\@[a-z]+|\*|-))?/ and do {
+ push @endwstack, $endw;
+ push @icstack, $ic;
+ if (defined $1) {
+ $ic = $1;
+ } else {
+ $ic = '*';
+ }
+ $_ = "\n=over 4\n";
+ $endw = "itemize";
+ };
+
+ /^\@enumerate(?:\s+([a-zA-Z0-9]+))?/ and do {
+ push @endwstack, $endw;
+ push @icstack, $ic;
+ if (defined $1) {
+ $ic = $1 . ".";
+ } else {
+ $ic = "1.";
+ }
+ $_ = "\n=over 4\n";
+ $endw = "enumerate";
+ };
+
+ /^\@multitable\s.*/ and do {
+ push @endwstack, $endw;
+ $endw = "multitable";
+ $_ = "\n=over 4\n";
+ };
+
+ /^\@([fv]?table)\s+(\@[a-z]+)/ and do {
+ push @endwstack, $endw;
+ push @icstack, $ic;
+ $endw = $1;
+ $ic = $2;
+ $ic =~ s/\@(?:samp|strong|key|gcctabopt|option|env)/B/;
+ $ic =~ s/\@(?:code|kbd)/C/;
+ $ic =~ s/\@(?:dfn|var|emph|cite|i)/I/;
+ $ic =~ s/\@(?:file)/F/;
+ $_ = "\n=over 4\n";
+ };
+
+ /^\@((?:small)?example|display)/ and do {
+ push @endwstack, $endw;
+ $endw = $1;
+ $shift = "\t";
+ $_ = ""; # need a paragraph break
+ };
+
+ /^\@item\s+(.*\S)\s*$/ and $endw eq "multitable" and do {
+ @columns = ();
+ for $column (split (/\s*\@tab\s*/, $1)) {
+ # @strong{...} is used a @headitem work-alike
+ $column =~ s/^\@strong{(.*)}$/$1/;
+ push @columns, $column;
+ }
+ $_ = "\n=item ".join (" : ", @columns)."\n";
+ };
+
+ /^\@itemx?\s*(.+)?$/ and do {
+ if (defined $1) {
+ # Entity escapes prevent munging by the <> processing below.
+ $_ = "\n=item $ic\<$1\>\n";
+ } else {
+ $_ = "\n=item $ic\n";
+ $ic =~ y/A-Ya-y/B-Zb-z/;
+ $ic =~ s/(\d+)/$1 + 1/eg;
+ }
+ };
+
+ $section .= $shift.$_."\n";
+}
+# End of current file.
+close($inf);
+$inf = pop @instack;
+}
+
+die "No filename or title\n" unless defined $fn && defined $tl;
+
+$sects{NAME} = "$fn \- $tl\n";
+$sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES};
+
+for $sect (qw(NAME SYNOPSIS DESCRIPTION OPTIONS ENVIRONMENT FILES
+ BUGS NOTES FOOTNOTES SEEALSO AUTHOR COPYRIGHT)) {
+ if(exists $sects{$sect}) {
+ $head = $sect;
+ $head =~ s/SEEALSO/SEE ALSO/;
+ print "=head1 $head\n\n";
+ print scalar unmunge ($sects{$sect});
+ print "\n";
+ }
+}
+
+sub usage
+{
+ die "usage: $0 [-D toggle...] [infile [outfile]]\n";
+}
+
+sub postprocess
+{
+ local $_ = $_[0];
+
+ # @value{foo} is replaced by whatever 'foo' is defined as.
+ while (m/(\@value\{([a-zA-Z0-9_-]+)\})/g) {
+ if (! exists $defs{$2}) {
+ print STDERR "Option $2 not defined\n";
+ s/\Q$1\E//;
+ } else {
+ $value = $defs{$2};
+ s/\Q$1\E/$value/;
+ }
+ }
+
+ # Formatting commands.
+ # Temporary escape for @r.
+ s/\@r\{([^\}]*)\}/R<$1>/g;
+ s/\@(?:dfn|var|emph|cite|i)\{([^\}]*)\}/I<$1>/g;
+ s/\@(?:code|kbd)\{([^\}]*)\}/C<$1>/g;
+ s/\@(?:gccoptlist|samp|strong|key|option|env|command|b)\{([^\}]*)\}/B<$1>/g;
+ s/\@sc\{([^\}]*)\}/\U$1/g;
+ s/\@file\{([^\}]*)\}/F<$1>/g;
+ s/\@w\{([^\}]*)\}/S<$1>/g;
+ s/\@(?:dmn|math)\{([^\}]*)\}/$1/g;
+
+ # keep references of the form @ref{...}, print them bold
+ s/\@(?:ref)\{([^\}]*)\}/B<$1>/g;
+
+ # Change double single quotes to double quotes.
+ s/''/"/g;
+ s/``/"/g;
+
+ # Cross references are thrown away, as are @noindent and @refill.
+ # (@noindent is impossible in .pod, and @refill is unnecessary.)
+ # @* is also impossible in .pod; we discard it and any newline that
+ # follows it. Similarly, our macro @gol must be discarded.
+
+ s/\(?\@xref\{(?:[^\}]*)\}(?:[^.<]|(?:<[^<>]*>))*\.\)?//g;
+ s/\s+\(\@pxref\{(?:[^\}]*)\}\)//g;
+ s/;\s+\@pxref\{(?:[^\}]*)\}//g;
+ s/\@noindent\s*//g;
+ s/\@refill//g;
+ s/\@gol//g;
+ s/\@\*\s*\n?//g;
+
+ # Anchors are thrown away
+ s/\@anchor\{(?:[^\}]*)\}//g;
+
+ # @uref can take one, two, or three arguments, with different
+ # semantics each time. @url and @email are just like @uref with
+ # one argument, for our purposes.
+ s/\@(?:uref|url|email)\{([^\},]*)\}/<B<$1>>/g;
+ s/\@uref\{([^\},]*),([^\},]*)\}/$2 (C<$1>)/g;
+ s/\@uref\{([^\},]*),([^\},]*),([^\},]*)\}/$3/g;
+
+ # Un-escape <> at this point.
+ s/</</g;
+ s/>/>/g;
+
+ # Now un-nest all B<>, I<>, R<>. Theoretically we could have
+ # indefinitely deep nesting; in practice, one level suffices.
+ 1 while s/([BIR])<([^<>]*)([BIR])<([^<>]*)>/$1<$2>$3<$4>$1</g;
+
+ # Replace R<...> with bare ...; eliminate empty markup, B<>;
+ # shift white space at the ends of [BI]<...> expressions outside
+ # the expression.
+ s/R<([^<>]*)>/$1/g;
+ s/[BI]<>//g;
+ s/([BI])<(\s+)([^>]+)>/$2$1<$3>/g;
+ s/([BI])<([^>]+?)(\s+)>/$1<$2>$3/g;
+
+ # Extract footnotes. This has to be done after all other
+ # processing because otherwise the regexp will choke on formatting
+ # inside @footnote.
+ while (/\@footnote/g) {
+ s/\@footnote\{([^\}]+)\}/[$fnno]/;
+ add_footnote($1, $fnno);
+ $fnno++;
+ }
+
+ return $_;
+}
+
+sub unmunge
+{
+ # Replace escaped symbols with their equivalents.
+ local $_ = $_[0];
+
+ s/</E<lt>/g;
+ s/>/E<gt>/g;
+ s/{/\{/g;
+ s/}/\}/g;
+ s/&at;/\@/g;
+ s/&/&/g;
+ return $_;
+}
+
+sub add_footnote
+{
+ unless (exists $sects{FOOTNOTES}) {
+ $sects{FOOTNOTES} = "\n=over 4\n\n";
+ }
+
+ $sects{FOOTNOTES} .= "=item $fnno.\n\n"; $fnno++;
+ $sects{FOOTNOTES} .= $_[0];
+ $sects{FOOTNOTES} .= "\n\n";
+}
+
+# stolen from Symbol.pm
+{
+ my $genseq = 0;
+ sub gensym
+ {
+ my $name = "GEN" . $genseq++;
+ my $ref = \*{$name};
+ delete $::{$name};
+ return $ref;
+ }
+}
diff --git a/scripts/tracetool b/scripts/tracetool
new file mode 100755
index 0000000..fce491c
--- /dev/null
+++ b/scripts/tracetool
@@ -0,0 +1,573 @@
+#!/bin/sh
+#
+# Code generator for trace events
+#
+# Copyright IBM, Corp. 2010
+#
+# This work is licensed under the terms of the GNU GPL, version 2. See
+# the COPYING file in the top-level directory.
+
+# Disable pathname expansion, makes processing text with '*' characters simpler
+set -f
+
+usage()
+{
+ cat >&2 <<EOF
+usage: $0 [--nop | --simple | --ust] [-h | -c]
+Generate tracing code for a file on stdin.
+
+Backends:
+ --nop Tracing disabled
+ --simple Simple built-in backend
+ --ust LTTng User Space Tracing backend
+ --dtrace DTrace/SystemTAP backend
+
+Output formats:
+ -h Generate .h file
+ -c Generate .c file
+ -d Generate .d file (DTrace only)
+ --stap Generate .stp file (DTrace with SystemTAP only)
+
+Options:
+ --binary [path] Full path to QEMU binary
+ --target-arch [arch] QEMU emulator target arch
+ --target-type [type] QEMU emulator target type ('system' or 'user')
+
+EOF
+ exit 1
+}
+
+# Get the name of a trace event
+get_name()
+{
+ echo ${1%%\(*}
+}
+
+# Get the argument list of a trace event, including types and names
+get_args()
+{
+ local args
+ args=${1#*\(}
+ args=${args%\)*}
+ echo "$args"
+}
+
+# Get the argument name list of a trace event
+get_argnames()
+{
+ local nfields field name sep
+ nfields=0
+ sep="$2"
+ for field in $(get_args "$1"); do
+ nfields=$((nfields + 1))
+
+ # Drop pointer star
+ field=${field#\*}
+
+ # Only argument names have commas at the end
+ name=${field%,}
+ test "$field" = "$name" && continue
+
+ printf "%s%s " $name $sep
+ done
+
+ # Last argument name
+ if [ "$nfields" -gt 1 ]
+ then
+ printf "%s" "$name"
+ fi
+}
+
+# Get the number of arguments to a trace event
+get_argc()
+{
+ local name argc
+ argc=0
+ for name in $(get_argnames "$1", ","); do
+ argc=$((argc + 1))
+ done
+ echo $argc
+}
+
+# Get the format string for a trace event
+get_fmt()
+{
+ local fmt
+ fmt=${1#*\"}
+ fmt=${fmt%\"*}
+ echo "$fmt"
+}
+
+# Get the state of a trace event
+get_state()
+{
+ local str disable state
+ str=$(get_name "$1")
+ disable=${str##disable }
+ if [ "$disable" = "$str" ] ; then
+ state=1
+ else
+ state=0
+ fi
+ echo "$state"
+}
+
+linetoh_begin_nop()
+{
+ return
+}
+
+linetoh_nop()
+{
+ local name args
+ name=$(get_name "$1")
+ args=$(get_args "$1")
+
+ # Define an empty function for the trace event
+ cat <<EOF
+static inline void trace_$name($args)
+{
+}
+EOF
+}
+
+linetoh_end_nop()
+{
+ return
+}
+
+linetoc_begin_nop()
+{
+ return
+}
+
+linetoc_nop()
+{
+ # No need for function definitions in nop backend
+ return
+}
+
+linetoc_end_nop()
+{
+ return
+}
+
+linetoh_begin_simple()
+{
+ cat <<EOF
+#include "simpletrace.h"
+EOF
+
+ simple_event_num=0
+}
+
+cast_args_to_uint64_t()
+{
+ local arg
+ for arg in $(get_argnames "$1", ","); do
+ printf "%s" "(uint64_t)(uintptr_t)$arg"
+ done
+}
+
+linetoh_simple()
+{
+ local name args argc trace_args state
+ name=$(get_name "$1")
+ args=$(get_args "$1")
+ argc=$(get_argc "$1")
+ state=$(get_state "$1")
+ if [ "$state" = "0" ]; then
+ name=${name##disable }
+ fi
+
+ trace_args="$simple_event_num"
+ if [ "$argc" -gt 0 ]
+ then
+ trace_args="$trace_args, $(cast_args_to_uint64_t "$1")"
+ fi
+
+ cat <<EOF
+static inline void trace_$name($args)
+{
+ trace$argc($trace_args);
+}
+EOF
+
+ simple_event_num=$((simple_event_num + 1))
+}
+
+linetoh_end_simple()
+{
+ cat <<EOF
+#define NR_TRACE_EVENTS $simple_event_num
+extern TraceEvent trace_list[NR_TRACE_EVENTS];
+EOF
+}
+
+linetoc_begin_simple()
+{
+ cat <<EOF
+#include "trace.h"
+
+TraceEvent trace_list[] = {
+EOF
+ simple_event_num=0
+
+}
+
+linetoc_simple()
+{
+ local name state
+ name=$(get_name "$1")
+ state=$(get_state "$1")
+ if [ "$state" = "0" ] ; then
+ name=${name##disable }
+ fi
+ cat <<EOF
+{.tp_name = "$name", .state=$state},
+EOF
+ simple_event_num=$((simple_event_num + 1))
+}
+
+linetoc_end_simple()
+{
+ cat <<EOF
+};
+EOF
+}
+
+# Clean up after UST headers which pollute the namespace
+ust_clean_namespace() {
+ cat <<EOF
+#undef mutex_lock
+#undef mutex_unlock
+#undef inline
+#undef wmb
+EOF
+}
+
+linetoh_begin_ust()
+{
+ echo "#include <ust/tracepoint.h>"
+ ust_clean_namespace
+}
+
+linetoh_ust()
+{
+ local name args argnames
+ name=$(get_name "$1")
+ args=$(get_args "$1")
+ argnames=$(get_argnames "$1", ",")
+
+ cat <<EOF
+DECLARE_TRACE(ust_$name, TP_PROTO($args), TP_ARGS($argnames));
+#define trace_$name trace_ust_$name
+EOF
+}
+
+linetoh_end_ust()
+{
+ return
+}
+
+linetoc_begin_ust()
+{
+ cat <<EOF
+#include <ust/marker.h>
+$(ust_clean_namespace)
+#include "trace.h"
+EOF
+}
+
+linetoc_ust()
+{
+ local name args argnames fmt
+ name=$(get_name "$1")
+ args=$(get_args "$1")
+ argnames=$(get_argnames "$1", ",")
+ fmt=$(get_fmt "$1")
+
+ cat <<EOF
+DEFINE_TRACE(ust_$name);
+
+static void ust_${name}_probe($args)
+{
+ trace_mark(ust, $name, "$fmt", $argnames);
+}
+EOF
+
+ # Collect names for later
+ names="$names $name"
+}
+
+linetoc_end_ust()
+{
+ cat <<EOF
+static void __attribute__((constructor)) trace_init(void)
+{
+EOF
+
+ for name in $names; do
+ cat <<EOF
+ register_trace_ust_$name(ust_${name}_probe);
+EOF
+ done
+
+ echo "}"
+}
+
+linetoh_begin_dtrace()
+{
+ cat <<EOF
+#include "trace-dtrace.h"
+EOF
+}
+
+linetoh_dtrace()
+{
+ local name args argnames state nameupper
+ name=$(get_name "$1")
+ args=$(get_args "$1")
+ argnames=$(get_argnames "$1", ",")
+ state=$(get_state "$1")
+ if [ "$state" = "0" ] ; then
+ name=${name##disable }
+ fi
+
+ nameupper=`echo $name | tr '[:lower:]' '[:upper:]'`
+
+ # Define an empty function for the trace event
+ cat <<EOF
+static inline void trace_$name($args) {
+ if (QEMU_${nameupper}_ENABLED()) {
+ QEMU_${nameupper}($argnames);
+ }
+}
+EOF
+}
+
+linetoh_end_dtrace()
+{
+ return
+}
+
+linetoc_begin_dtrace()
+{
+ return
+}
+
+linetoc_dtrace()
+{
+ # No need for function definitions in dtrace backend
+ return
+}
+
+linetoc_end_dtrace()
+{
+ return
+}
+
+linetod_begin_dtrace()
+{
+ cat <<EOF
+provider qemu {
+EOF
+}
+
+linetod_dtrace()
+{
+ local name args state
+ name=$(get_name "$1")
+ args=$(get_args "$1")
+ state=$(get_state "$1")
+ if [ "$state" = "0" ] ; then
+ name=${name##disable }
+ fi
+
+ # DTrace provider syntax expects foo() for empty
+ # params, not foo(void)
+ if [ "$args" = "void" ]; then
+ args=""
+ fi
+
+ # Define prototype for probe arguments
+ cat <<EOF
+ probe $name($args);
+EOF
+}
+
+linetod_end_dtrace()
+{
+ cat <<EOF
+};
+EOF
+}
+
+linetostap_begin_dtrace()
+{
+ return
+}
+
+linetostap_dtrace()
+{
+ local i arg name args arglist state
+ name=$(get_name "$1")
+ args=$(get_args "$1")
+ arglist=$(get_argnames "$1", "")
+ state=$(get_state "$1")
+ if [ "$state" = "0" ] ; then
+ name=${name##disable }
+ fi
+
+ # Define prototype for probe arguments
+ cat <<EOF
+probe qemu.$targettype.$targetarch.$name = process("$binary").mark("$name")
+{
+EOF
+
+ i=1
+ for arg in $arglist
+ do
+ # 'limit' is a reserved keyword
+ if [ "$arg" = "limit" ]; then
+ arg="_limit"
+ fi
+ cat <<EOF
+ $arg = \$arg$i;
+EOF
+ i="$((i+1))"
+ done
+
+ cat <<EOF
+}
+EOF
+}
+
+linetostap_end_dtrace()
+{
+ return
+}
+
+# Process stdin by calling begin, line, and end functions for the backend
+convert()
+{
+ local begin process_line end str disable
+ begin="lineto$1_begin_$backend"
+ process_line="lineto$1_$backend"
+ end="lineto$1_end_$backend"
+
+ "$begin"
+
+ while read -r str; do
+ # Skip comments and empty lines
+ test -z "${str%%#*}" && continue
+
+ # Process the line. The nop backend handles disabled lines.
+ disable=${str%%disable *}
+ echo
+ if test -z "$disable"; then
+ # Pass the disabled state as an arg for the simple
+ # or DTrace backends which handle it dynamically.
+ # For all other backends, call lineto$1_nop()
+ if [ $backend = "simple" -o "$backend" = "dtrace" ]; then
+ "$process_line" "$str"
+ else
+ "lineto$1_nop" "${str##disable }"
+ fi
+ else
+ "$process_line" "$str"
+ fi
+ done
+
+ echo
+ "$end"
+}
+
+tracetoh()
+{
+ cat <<EOF
+#ifndef TRACE_H
+#define TRACE_H
+
+/* This file is autogenerated by tracetool, do not edit. */
+
+#include "qemu-common.h"
+EOF
+ convert h
+ echo "#endif /* TRACE_H */"
+}
+
+tracetoc()
+{
+ echo "/* This file is autogenerated by tracetool, do not edit. */"
+ convert c
+}
+
+tracetod()
+{
+ if [ $backend != "dtrace" ]; then
+ echo "DTrace probe generator not applicable to $backend backend"
+ exit 1
+ fi
+ echo "/* This file is autogenerated by tracetool, do not edit. */"
+ convert d
+}
+
+tracetostap()
+{
+ if [ $backend != "dtrace" ]; then
+ echo "SystemTAP tapset generator not applicable to $backend backend"
+ exit 1
+ fi
+ if [ -z "$binary" ]; then
+ echo "--binary is required for SystemTAP tapset generator"
+ exit 1
+ fi
+ if [ -z "$targettype" ]; then
+ echo "--target-type is required for SystemTAP tapset generator"
+ exit 1
+ fi
+ if [ -z "$targetarch" ]; then
+ echo "--target-arch is required for SystemTAP tapset generator"
+ exit 1
+ fi
+ echo "/* This file is autogenerated by tracetool, do not edit. */"
+ convert stap
+}
+
+
+backend=
+output=
+binary=
+targettype=
+targetarch=
+
+
+until [ -z "$1" ]
+do
+ case "$1" in
+ "--nop" | "--simple" | "--ust" | "--dtrace") backend="${1#--}" ;;
+
+ "--binary") shift ; binary="$1" ;;
+ "--target-arch") shift ; targetarch="$1" ;;
+ "--target-type") shift ; targettype="$1" ;;
+
+ "-h" | "-c" | "-d") output="${1#-}" ;;
+ "--stap") output="${1#--}" ;;
+
+ "--check-backend") exit 0 ;; # used by ./configure to test for backend
+
+ *)
+ usage;;
+ esac
+ shift
+done
+
+if [ "$backend" = "" -o "$output" = "" ]; then
+ usage
+fi
+
+gen="traceto$output"
+"$gen"
+
+exit 0
diff --git a/simpletrace.py b/simpletrace.py
deleted file mode 100755
index 553a727..0000000
--- a/simpletrace.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/env python
-#
-# Pretty-printer for simple trace backend binary trace files
-#
-# Copyright IBM, Corp. 2010
-#
-# This work is licensed under the terms of the GNU GPL, version 2. See
-# the COPYING file in the top-level directory.
-#
-# For help see docs/tracing.txt
-
-import sys
-import struct
-import re
-
-header_event_id = 0xffffffffffffffff
-header_magic = 0xf2b177cb0aa429b4
-header_version = 0
-
-trace_fmt = '=QQQQQQQQ'
-trace_len = struct.calcsize(trace_fmt)
-event_re = re.compile(r'(disable\s+)?([a-zA-Z0-9_]+)\(([^)]*)\).*')
-
-def err(msg):
- sys.stderr.write(msg + '\n')
- sys.exit(1)
-
-def parse_events(fobj):
- """Parse a trace-events file."""
-
- def get_argnames(args):
- """Extract argument names from a parameter list."""
- return tuple(arg.split()[-1].lstrip('*') for arg in args.split(','))
-
- events = {}
- event_num = 0
- for line in fobj:
- m = event_re.match(line.strip())
- if m is None:
- continue
-
- disable, name, args = m.groups()
- events[event_num] = (name,) + get_argnames(args)
- event_num += 1
- return events
-
-def read_record(fobj):
- """Deserialize a trace record from a file."""
- s = fobj.read(trace_len)
- if len(s) != trace_len:
- return None
- return struct.unpack(trace_fmt, s)
-
-def read_trace_file(fobj):
- """Deserialize trace records from a file."""
- header = read_record(fobj)
- if header is None or \
- header[0] != header_event_id or \
- header[1] != header_magic or \
- header[2] != header_version:
- err('not a trace file or incompatible version')
-
- while True:
- rec = read_record(fobj)
- if rec is None:
- break
-
- yield rec
-
-class Formatter(object):
- def __init__(self, events):
- self.events = events
- self.last_timestamp = None
-
- def format_record(self, rec):
- if self.last_timestamp is None:
- self.last_timestamp = rec[1]
- delta_ns = rec[1] - self.last_timestamp
- self.last_timestamp = rec[1]
-
- event = self.events[rec[0]]
- fields = [event[0], '%0.3f' % (delta_ns / 1000.0)]
- for i in xrange(1, len(event)):
- fields.append('%s=0x%x' % (event[i], rec[i + 1]))
- return ' '.join(fields)
-
-if len(sys.argv) != 3:
- err('usage: %s <trace-events> <trace-file>' % sys.argv[0])
-
-events = parse_events(open(sys.argv[1], 'r'))
-formatter = Formatter(events)
-for rec in read_trace_file(open(sys.argv[2], 'rb')):
- print formatter.format_record(rec)
diff --git a/texi2pod.pl b/texi2pod.pl
deleted file mode 100755
index 9ed056a..0000000
--- a/texi2pod.pl
+++ /dev/null
@@ -1,477 +0,0 @@
-#! /usr/bin/perl -w
-
-# Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
-
-# This file is part of GCC.
-
-# GCC 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, or (at your option)
-# any later version.
-
-# GCC is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING. If not,
-# see <http://www.gnu.org/licenses/>.
-
-# This does trivial (and I mean _trivial_) conversion of Texinfo
-# markup to Perl POD format. It's intended to be used to extract
-# something suitable for a manpage from a Texinfo document.
-
-$output = 0;
-$skipping = 0;
-%sects = ();
-$section = "";
- at icstack = ();
- at endwstack = ();
- at skstack = ();
- at instack = ();
-$shift = "";
-%defs = ();
-$fnno = 1;
-$inf = "";
-$ibase = "";
- at ipath = ();
-
-while ($_ = shift) {
- if (/^-D(.*)$/) {
- if ($1 ne "") {
- $flag = $1;
- } else {
- $flag = shift;
- }
- $value = "";
- ($flag, $value) = ($flag =~ /^([^=]+)(?:=(.+))?/);
- die "no flag specified for -D\n"
- unless $flag ne "";
- die "flags may only contain letters, digits, hyphens, dashes and underscores\n"
- unless $flag =~ /^[a-zA-Z0-9_-]+$/;
- $defs{$flag} = $value;
- } elsif (/^-I(.*)$/) {
- if ($1 ne "") {
- $flag = $1;
- } else {
- $flag = shift;
- }
- push (@ipath, $flag);
- } elsif (/^-/) {
- usage();
- } else {
- $in = $_, next unless defined $in;
- $out = $_, next unless defined $out;
- usage();
- }
-}
-
-if (defined $in) {
- $inf = gensym();
- open($inf, "<$in") or die "opening \"$in\": $!\n";
- $ibase = $1 if $in =~ m|^(.+)/[^/]+$|;
-} else {
- $inf = \*STDIN;
-}
-
-if (defined $out) {
- open(STDOUT, ">$out") or die "opening \"$out\": $!\n";
-}
-
-while(defined $inf) {
-while(<$inf>) {
- # Certain commands are discarded without further processing.
- /^\@(?:
- [a-z]+index # @*index: useful only in complete manual
- |need # @need: useful only in printed manual
- |(?:end\s+)?group # @group .. @end group: ditto
- |page # @page: ditto
- |node # @node: useful only in .info file
- |(?:end\s+)?ifnottex # @ifnottex .. @end ifnottex: use contents
- )\b/x and next;
-
- chomp;
-
- # Look for filename and title markers.
- /^\@setfilename\s+([^.]+)/ and $fn = $1, next;
- /^\@settitle\s+([^.]+)/ and $tl = postprocess($1), next;
-
- # Identify a man title but keep only the one we are interested in.
- /^\@c\s+man\s+title\s+([A-Za-z0-9-]+)\s+(.+)/ and do {
- if (exists $defs{$1}) {
- $fn = $1;
- $tl = postprocess($2);
- }
- next;
- };
-
- # Look for blocks surrounded by @c man begin SECTION ... @c man end.
- # This really oughta be @ifman ... @end ifman and the like, but such
- # would require rev'ing all other Texinfo translators.
- /^\@c\s+man\s+begin\s+([A-Z]+)\s+([A-Za-z0-9-]+)/ and do {
- $output = 1 if exists $defs{$2};
- $sect = $1;
- next;
- };
- /^\@c\s+man\s+begin\s+([A-Z]+)/ and $sect = $1, $output = 1, next;
- /^\@c\s+man\s+end/ and do {
- $sects{$sect} = "" unless exists $sects{$sect};
- $sects{$sect} .= postprocess($section);
- $section = "";
- $output = 0;
- next;
- };
-
- # handle variables
- /^\@set\s+([a-zA-Z0-9_-]+)\s*(.*)$/ and do {
- $defs{$1} = $2;
- next;
- };
- /^\@clear\s+([a-zA-Z0-9_-]+)/ and do {
- delete $defs{$1};
- next;
- };
-
- next unless $output;
-
- # Discard comments. (Can't do it above, because then we'd never see
- # @c man lines.)
- /^\@c\b/ and next;
-
- # End-block handler goes up here because it needs to operate even
- # if we are skipping.
- /^\@end\s+([a-z]+)/ and do {
- # Ignore @end foo, where foo is not an operation which may
- # cause us to skip, if we are presently skipping.
- my $ended = $1;
- next if $skipping && $ended !~ /^(?:ifset|ifclear|ignore|menu|iftex|copying)$/;
-
- die "\@end $ended without \@$ended at line $.\n" unless defined $endw;
- die "\@$endw ended by \@end $ended at line $.\n" unless $ended eq $endw;
-
- $endw = pop @endwstack;
-
- if ($ended =~ /^(?:ifset|ifclear|ignore|menu|iftex)$/) {
- $skipping = pop @skstack;
- next;
- } elsif ($ended =~ /^(?:example|smallexample|display)$/) {
- $shift = "";
- $_ = ""; # need a paragraph break
- } elsif ($ended =~ /^(?:itemize|enumerate|[fv]?table)$/) {
- $_ = "\n=back\n";
- $ic = pop @icstack;
- } elsif ($ended eq "multitable") {
- $_ = "\n=back\n";
- } else {
- die "unknown command \@end $ended at line $.\n";
- }
- };
-
- # We must handle commands which can cause skipping even while we
- # are skipping, otherwise we will not process nested conditionals
- # correctly.
- /^\@ifset\s+([a-zA-Z0-9_-]+)/ and do {
- push @endwstack, $endw;
- push @skstack, $skipping;
- $endw = "ifset";
- $skipping = 1 unless exists $defs{$1};
- next;
- };
-
- /^\@ifclear\s+([a-zA-Z0-9_-]+)/ and do {
- push @endwstack, $endw;
- push @skstack, $skipping;
- $endw = "ifclear";
- $skipping = 1 if exists $defs{$1};
- next;
- };
-
- /^\@(ignore|menu|iftex|copying)\b/ and do {
- push @endwstack, $endw;
- push @skstack, $skipping;
- $endw = $1;
- $skipping = 1;
- next;
- };
-
- next if $skipping;
-
- # Character entities. First the ones that can be replaced by raw text
- # or discarded outright:
- s/\@copyright\{\}/(c)/g;
- s/\@dots\{\}/.../g;
- s/\@enddots\{\}/..../g;
- s/\@([.!? ])/$1/g;
- s/\@[:-]//g;
- s/\@bullet(?:\{\})?/*/g;
- s/\@TeX\{\}/TeX/g;
- s/\@pounds\{\}/\#/g;
- s/\@minus(?:\{\})?/-/g;
- s/\\,/,/g;
-
- # Now the ones that have to be replaced by special escapes
- # (which will be turned back into text by unmunge())
- s/&/&/g;
- s/\@\{/{/g;
- s/\@\}/}/g;
- s/\@\@/&at;/g;
-
- # Inside a verbatim block, handle @var specially.
- if ($shift ne "") {
- s/\@var\{([^\}]*)\}/<$1>/g;
- }
-
- # POD doesn't interpret E<> inside a verbatim block.
- if ($shift eq "") {
- s/</</g;
- s/>/>/g;
- } else {
- s/</</g;
- s/>/>/g;
- }
-
- # Single line command handlers.
-
- /^\@include\s+(.+)$/ and do {
- push @instack, $inf;
- $inf = gensym();
- $file = postprocess($1);
-
- # Try cwd and $ibase, then explicit -I paths.
- $done = 0;
- foreach $path ("", $ibase, @ipath) {
- $mypath = $file;
- $mypath = $path . "/" . $mypath if ($path ne "");
- open($inf, "<" . $mypath) and ($done = 1, last);
- }
- die "cannot find $file" if !$done;
- next;
- };
-
- /^\@(?:section|unnumbered|unnumberedsec|center)\s+(.+)$/
- and $_ = "\n=head2 $1\n";
- /^\@subsection\s+(.+)$/
- and $_ = "\n=head3 $1\n";
- /^\@subsubsection\s+(.+)$/
- and $_ = "\n=head4 $1\n";
-
- # Block command handlers:
- /^\@itemize(?:\s+(\@[a-z]+|\*|-))?/ and do {
- push @endwstack, $endw;
- push @icstack, $ic;
- if (defined $1) {
- $ic = $1;
- } else {
- $ic = '*';
- }
- $_ = "\n=over 4\n";
- $endw = "itemize";
- };
-
- /^\@enumerate(?:\s+([a-zA-Z0-9]+))?/ and do {
- push @endwstack, $endw;
- push @icstack, $ic;
- if (defined $1) {
- $ic = $1 . ".";
- } else {
- $ic = "1.";
- }
- $_ = "\n=over 4\n";
- $endw = "enumerate";
- };
-
- /^\@multitable\s.*/ and do {
- push @endwstack, $endw;
- $endw = "multitable";
- $_ = "\n=over 4\n";
- };
-
- /^\@([fv]?table)\s+(\@[a-z]+)/ and do {
- push @endwstack, $endw;
- push @icstack, $ic;
- $endw = $1;
- $ic = $2;
- $ic =~ s/\@(?:samp|strong|key|gcctabopt|option|env)/B/;
- $ic =~ s/\@(?:code|kbd)/C/;
- $ic =~ s/\@(?:dfn|var|emph|cite|i)/I/;
- $ic =~ s/\@(?:file)/F/;
- $_ = "\n=over 4\n";
- };
-
- /^\@((?:small)?example|display)/ and do {
- push @endwstack, $endw;
- $endw = $1;
- $shift = "\t";
- $_ = ""; # need a paragraph break
- };
-
- /^\@item\s+(.*\S)\s*$/ and $endw eq "multitable" and do {
- @columns = ();
- for $column (split (/\s*\@tab\s*/, $1)) {
- # @strong{...} is used a @headitem work-alike
- $column =~ s/^\@strong{(.*)}$/$1/;
- push @columns, $column;
- }
- $_ = "\n=item ".join (" : ", @columns)."\n";
- };
-
- /^\@itemx?\s*(.+)?$/ and do {
- if (defined $1) {
- # Entity escapes prevent munging by the <> processing below.
- $_ = "\n=item $ic\<$1\>\n";
- } else {
- $_ = "\n=item $ic\n";
- $ic =~ y/A-Ya-y/B-Zb-z/;
- $ic =~ s/(\d+)/$1 + 1/eg;
- }
- };
-
- $section .= $shift.$_."\n";
-}
-# End of current file.
-close($inf);
-$inf = pop @instack;
-}
-
-die "No filename or title\n" unless defined $fn && defined $tl;
-
-$sects{NAME} = "$fn \- $tl\n";
-$sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES};
-
-for $sect (qw(NAME SYNOPSIS DESCRIPTION OPTIONS ENVIRONMENT FILES
- BUGS NOTES FOOTNOTES SEEALSO AUTHOR COPYRIGHT)) {
- if(exists $sects{$sect}) {
- $head = $sect;
- $head =~ s/SEEALSO/SEE ALSO/;
- print "=head1 $head\n\n";
- print scalar unmunge ($sects{$sect});
- print "\n";
- }
-}
-
-sub usage
-{
- die "usage: $0 [-D toggle...] [infile [outfile]]\n";
-}
-
-sub postprocess
-{
- local $_ = $_[0];
-
- # @value{foo} is replaced by whatever 'foo' is defined as.
- while (m/(\@value\{([a-zA-Z0-9_-]+)\})/g) {
- if (! exists $defs{$2}) {
- print STDERR "Option $2 not defined\n";
- s/\Q$1\E//;
- } else {
- $value = $defs{$2};
- s/\Q$1\E/$value/;
- }
- }
-
- # Formatting commands.
- # Temporary escape for @r.
- s/\@r\{([^\}]*)\}/R<$1>/g;
- s/\@(?:dfn|var|emph|cite|i)\{([^\}]*)\}/I<$1>/g;
- s/\@(?:code|kbd)\{([^\}]*)\}/C<$1>/g;
- s/\@(?:gccoptlist|samp|strong|key|option|env|command|b)\{([^\}]*)\}/B<$1>/g;
- s/\@sc\{([^\}]*)\}/\U$1/g;
- s/\@file\{([^\}]*)\}/F<$1>/g;
- s/\@w\{([^\}]*)\}/S<$1>/g;
- s/\@(?:dmn|math)\{([^\}]*)\}/$1/g;
-
- # keep references of the form @ref{...}, print them bold
- s/\@(?:ref)\{([^\}]*)\}/B<$1>/g;
-
- # Change double single quotes to double quotes.
- s/''/"/g;
- s/``/"/g;
-
- # Cross references are thrown away, as are @noindent and @refill.
- # (@noindent is impossible in .pod, and @refill is unnecessary.)
- # @* is also impossible in .pod; we discard it and any newline that
- # follows it. Similarly, our macro @gol must be discarded.
-
- s/\(?\@xref\{(?:[^\}]*)\}(?:[^.<]|(?:<[^<>]*>))*\.\)?//g;
- s/\s+\(\@pxref\{(?:[^\}]*)\}\)//g;
- s/;\s+\@pxref\{(?:[^\}]*)\}//g;
- s/\@noindent\s*//g;
- s/\@refill//g;
- s/\@gol//g;
- s/\@\*\s*\n?//g;
-
- # Anchors are thrown away
- s/\@anchor\{(?:[^\}]*)\}//g;
-
- # @uref can take one, two, or three arguments, with different
- # semantics each time. @url and @email are just like @uref with
- # one argument, for our purposes.
- s/\@(?:uref|url|email)\{([^\},]*)\}/<B<$1>>/g;
- s/\@uref\{([^\},]*),([^\},]*)\}/$2 (C<$1>)/g;
- s/\@uref\{([^\},]*),([^\},]*),([^\},]*)\}/$3/g;
-
- # Un-escape <> at this point.
- s/</</g;
- s/>/>/g;
-
- # Now un-nest all B<>, I<>, R<>. Theoretically we could have
- # indefinitely deep nesting; in practice, one level suffices.
- 1 while s/([BIR])<([^<>]*)([BIR])<([^<>]*)>/$1<$2>$3<$4>$1</g;
-
- # Replace R<...> with bare ...; eliminate empty markup, B<>;
- # shift white space at the ends of [BI]<...> expressions outside
- # the expression.
- s/R<([^<>]*)>/$1/g;
- s/[BI]<>//g;
- s/([BI])<(\s+)([^>]+)>/$2$1<$3>/g;
- s/([BI])<([^>]+?)(\s+)>/$1<$2>$3/g;
-
- # Extract footnotes. This has to be done after all other
- # processing because otherwise the regexp will choke on formatting
- # inside @footnote.
- while (/\@footnote/g) {
- s/\@footnote\{([^\}]+)\}/[$fnno]/;
- add_footnote($1, $fnno);
- $fnno++;
- }
-
- return $_;
-}
-
-sub unmunge
-{
- # Replace escaped symbols with their equivalents.
- local $_ = $_[0];
-
- s/</E<lt>/g;
- s/>/E<gt>/g;
- s/{/\{/g;
- s/}/\}/g;
- s/&at;/\@/g;
- s/&/&/g;
- return $_;
-}
-
-sub add_footnote
-{
- unless (exists $sects{FOOTNOTES}) {
- $sects{FOOTNOTES} = "\n=over 4\n\n";
- }
-
- $sects{FOOTNOTES} .= "=item $fnno.\n\n"; $fnno++;
- $sects{FOOTNOTES} .= $_[0];
- $sects{FOOTNOTES} .= "\n\n";
-}
-
-# stolen from Symbol.pm
-{
- my $genseq = 0;
- sub gensym
- {
- my $name = "GEN" . $genseq++;
- my $ref = \*{$name};
- delete $::{$name};
- return $ref;
- }
-}
diff --git a/tracetool b/tracetool
deleted file mode 100755
index fce491c..0000000
--- a/tracetool
+++ /dev/null
@@ -1,573 +0,0 @@
-#!/bin/sh
-#
-# Code generator for trace events
-#
-# Copyright IBM, Corp. 2010
-#
-# This work is licensed under the terms of the GNU GPL, version 2. See
-# the COPYING file in the top-level directory.
-
-# Disable pathname expansion, makes processing text with '*' characters simpler
-set -f
-
-usage()
-{
- cat >&2 <<EOF
-usage: $0 [--nop | --simple | --ust] [-h | -c]
-Generate tracing code for a file on stdin.
-
-Backends:
- --nop Tracing disabled
- --simple Simple built-in backend
- --ust LTTng User Space Tracing backend
- --dtrace DTrace/SystemTAP backend
-
-Output formats:
- -h Generate .h file
- -c Generate .c file
- -d Generate .d file (DTrace only)
- --stap Generate .stp file (DTrace with SystemTAP only)
-
-Options:
- --binary [path] Full path to QEMU binary
- --target-arch [arch] QEMU emulator target arch
- --target-type [type] QEMU emulator target type ('system' or 'user')
-
-EOF
- exit 1
-}
-
-# Get the name of a trace event
-get_name()
-{
- echo ${1%%\(*}
-}
-
-# Get the argument list of a trace event, including types and names
-get_args()
-{
- local args
- args=${1#*\(}
- args=${args%\)*}
- echo "$args"
-}
-
-# Get the argument name list of a trace event
-get_argnames()
-{
- local nfields field name sep
- nfields=0
- sep="$2"
- for field in $(get_args "$1"); do
- nfields=$((nfields + 1))
-
- # Drop pointer star
- field=${field#\*}
-
- # Only argument names have commas at the end
- name=${field%,}
- test "$field" = "$name" && continue
-
- printf "%s%s " $name $sep
- done
-
- # Last argument name
- if [ "$nfields" -gt 1 ]
- then
- printf "%s" "$name"
- fi
-}
-
-# Get the number of arguments to a trace event
-get_argc()
-{
- local name argc
- argc=0
- for name in $(get_argnames "$1", ","); do
- argc=$((argc + 1))
- done
- echo $argc
-}
-
-# Get the format string for a trace event
-get_fmt()
-{
- local fmt
- fmt=${1#*\"}
- fmt=${fmt%\"*}
- echo "$fmt"
-}
-
-# Get the state of a trace event
-get_state()
-{
- local str disable state
- str=$(get_name "$1")
- disable=${str##disable }
- if [ "$disable" = "$str" ] ; then
- state=1
- else
- state=0
- fi
- echo "$state"
-}
-
-linetoh_begin_nop()
-{
- return
-}
-
-linetoh_nop()
-{
- local name args
- name=$(get_name "$1")
- args=$(get_args "$1")
-
- # Define an empty function for the trace event
- cat <<EOF
-static inline void trace_$name($args)
-{
-}
-EOF
-}
-
-linetoh_end_nop()
-{
- return
-}
-
-linetoc_begin_nop()
-{
- return
-}
-
-linetoc_nop()
-{
- # No need for function definitions in nop backend
- return
-}
-
-linetoc_end_nop()
-{
- return
-}
-
-linetoh_begin_simple()
-{
- cat <<EOF
-#include "simpletrace.h"
-EOF
-
- simple_event_num=0
-}
-
-cast_args_to_uint64_t()
-{
- local arg
- for arg in $(get_argnames "$1", ","); do
- printf "%s" "(uint64_t)(uintptr_t)$arg"
- done
-}
-
-linetoh_simple()
-{
- local name args argc trace_args state
- name=$(get_name "$1")
- args=$(get_args "$1")
- argc=$(get_argc "$1")
- state=$(get_state "$1")
- if [ "$state" = "0" ]; then
- name=${name##disable }
- fi
-
- trace_args="$simple_event_num"
- if [ "$argc" -gt 0 ]
- then
- trace_args="$trace_args, $(cast_args_to_uint64_t "$1")"
- fi
-
- cat <<EOF
-static inline void trace_$name($args)
-{
- trace$argc($trace_args);
-}
-EOF
-
- simple_event_num=$((simple_event_num + 1))
-}
-
-linetoh_end_simple()
-{
- cat <<EOF
-#define NR_TRACE_EVENTS $simple_event_num
-extern TraceEvent trace_list[NR_TRACE_EVENTS];
-EOF
-}
-
-linetoc_begin_simple()
-{
- cat <<EOF
-#include "trace.h"
-
-TraceEvent trace_list[] = {
-EOF
- simple_event_num=0
-
-}
-
-linetoc_simple()
-{
- local name state
- name=$(get_name "$1")
- state=$(get_state "$1")
- if [ "$state" = "0" ] ; then
- name=${name##disable }
- fi
- cat <<EOF
-{.tp_name = "$name", .state=$state},
-EOF
- simple_event_num=$((simple_event_num + 1))
-}
-
-linetoc_end_simple()
-{
- cat <<EOF
-};
-EOF
-}
-
-# Clean up after UST headers which pollute the namespace
-ust_clean_namespace() {
- cat <<EOF
-#undef mutex_lock
-#undef mutex_unlock
-#undef inline
-#undef wmb
-EOF
-}
-
-linetoh_begin_ust()
-{
- echo "#include <ust/tracepoint.h>"
- ust_clean_namespace
-}
-
-linetoh_ust()
-{
- local name args argnames
- name=$(get_name "$1")
- args=$(get_args "$1")
- argnames=$(get_argnames "$1", ",")
-
- cat <<EOF
-DECLARE_TRACE(ust_$name, TP_PROTO($args), TP_ARGS($argnames));
-#define trace_$name trace_ust_$name
-EOF
-}
-
-linetoh_end_ust()
-{
- return
-}
-
-linetoc_begin_ust()
-{
- cat <<EOF
-#include <ust/marker.h>
-$(ust_clean_namespace)
-#include "trace.h"
-EOF
-}
-
-linetoc_ust()
-{
- local name args argnames fmt
- name=$(get_name "$1")
- args=$(get_args "$1")
- argnames=$(get_argnames "$1", ",")
- fmt=$(get_fmt "$1")
-
- cat <<EOF
-DEFINE_TRACE(ust_$name);
-
-static void ust_${name}_probe($args)
-{
- trace_mark(ust, $name, "$fmt", $argnames);
-}
-EOF
-
- # Collect names for later
- names="$names $name"
-}
-
-linetoc_end_ust()
-{
- cat <<EOF
-static void __attribute__((constructor)) trace_init(void)
-{
-EOF
-
- for name in $names; do
- cat <<EOF
- register_trace_ust_$name(ust_${name}_probe);
-EOF
- done
-
- echo "}"
-}
-
-linetoh_begin_dtrace()
-{
- cat <<EOF
-#include "trace-dtrace.h"
-EOF
-}
-
-linetoh_dtrace()
-{
- local name args argnames state nameupper
- name=$(get_name "$1")
- args=$(get_args "$1")
- argnames=$(get_argnames "$1", ",")
- state=$(get_state "$1")
- if [ "$state" = "0" ] ; then
- name=${name##disable }
- fi
-
- nameupper=`echo $name | tr '[:lower:]' '[:upper:]'`
-
- # Define an empty function for the trace event
- cat <<EOF
-static inline void trace_$name($args) {
- if (QEMU_${nameupper}_ENABLED()) {
- QEMU_${nameupper}($argnames);
- }
-}
-EOF
-}
-
-linetoh_end_dtrace()
-{
- return
-}
-
-linetoc_begin_dtrace()
-{
- return
-}
-
-linetoc_dtrace()
-{
- # No need for function definitions in dtrace backend
- return
-}
-
-linetoc_end_dtrace()
-{
- return
-}
-
-linetod_begin_dtrace()
-{
- cat <<EOF
-provider qemu {
-EOF
-}
-
-linetod_dtrace()
-{
- local name args state
- name=$(get_name "$1")
- args=$(get_args "$1")
- state=$(get_state "$1")
- if [ "$state" = "0" ] ; then
- name=${name##disable }
- fi
-
- # DTrace provider syntax expects foo() for empty
- # params, not foo(void)
- if [ "$args" = "void" ]; then
- args=""
- fi
-
- # Define prototype for probe arguments
- cat <<EOF
- probe $name($args);
-EOF
-}
-
-linetod_end_dtrace()
-{
- cat <<EOF
-};
-EOF
-}
-
-linetostap_begin_dtrace()
-{
- return
-}
-
-linetostap_dtrace()
-{
- local i arg name args arglist state
- name=$(get_name "$1")
- args=$(get_args "$1")
- arglist=$(get_argnames "$1", "")
- state=$(get_state "$1")
- if [ "$state" = "0" ] ; then
- name=${name##disable }
- fi
-
- # Define prototype for probe arguments
- cat <<EOF
-probe qemu.$targettype.$targetarch.$name = process("$binary").mark("$name")
-{
-EOF
-
- i=1
- for arg in $arglist
- do
- # 'limit' is a reserved keyword
- if [ "$arg" = "limit" ]; then
- arg="_limit"
- fi
- cat <<EOF
- $arg = \$arg$i;
-EOF
- i="$((i+1))"
- done
-
- cat <<EOF
-}
-EOF
-}
-
-linetostap_end_dtrace()
-{
- return
-}
-
-# Process stdin by calling begin, line, and end functions for the backend
-convert()
-{
- local begin process_line end str disable
- begin="lineto$1_begin_$backend"
- process_line="lineto$1_$backend"
- end="lineto$1_end_$backend"
-
- "$begin"
-
- while read -r str; do
- # Skip comments and empty lines
- test -z "${str%%#*}" && continue
-
- # Process the line. The nop backend handles disabled lines.
- disable=${str%%disable *}
- echo
- if test -z "$disable"; then
- # Pass the disabled state as an arg for the simple
- # or DTrace backends which handle it dynamically.
- # For all other backends, call lineto$1_nop()
- if [ $backend = "simple" -o "$backend" = "dtrace" ]; then
- "$process_line" "$str"
- else
- "lineto$1_nop" "${str##disable }"
- fi
- else
- "$process_line" "$str"
- fi
- done
-
- echo
- "$end"
-}
-
-tracetoh()
-{
- cat <<EOF
-#ifndef TRACE_H
-#define TRACE_H
-
-/* This file is autogenerated by tracetool, do not edit. */
-
-#include "qemu-common.h"
-EOF
- convert h
- echo "#endif /* TRACE_H */"
-}
-
-tracetoc()
-{
- echo "/* This file is autogenerated by tracetool, do not edit. */"
- convert c
-}
-
-tracetod()
-{
- if [ $backend != "dtrace" ]; then
- echo "DTrace probe generator not applicable to $backend backend"
- exit 1
- fi
- echo "/* This file is autogenerated by tracetool, do not edit. */"
- convert d
-}
-
-tracetostap()
-{
- if [ $backend != "dtrace" ]; then
- echo "SystemTAP tapset generator not applicable to $backend backend"
- exit 1
- fi
- if [ -z "$binary" ]; then
- echo "--binary is required for SystemTAP tapset generator"
- exit 1
- fi
- if [ -z "$targettype" ]; then
- echo "--target-type is required for SystemTAP tapset generator"
- exit 1
- fi
- if [ -z "$targetarch" ]; then
- echo "--target-arch is required for SystemTAP tapset generator"
- exit 1
- fi
- echo "/* This file is autogenerated by tracetool, do not edit. */"
- convert stap
-}
-
-
-backend=
-output=
-binary=
-targettype=
-targetarch=
-
-
-until [ -z "$1" ]
-do
- case "$1" in
- "--nop" | "--simple" | "--ust" | "--dtrace") backend="${1#--}" ;;
-
- "--binary") shift ; binary="$1" ;;
- "--target-arch") shift ; targetarch="$1" ;;
- "--target-type") shift ; targettype="$1" ;;
-
- "-h" | "-c" | "-d") output="${1#-}" ;;
- "--stap") output="${1#--}" ;;
-
- "--check-backend") exit 0 ;; # used by ./configure to test for backend
-
- *)
- usage;;
- esac
- shift
-done
-
-if [ "$backend" = "" -o "$output" = "" ]; then
- usage
-fi
-
-gen="traceto$output"
-"$gen"
-
-exit 0
commit 8e5977e5f588b2d4b74831d11860191f815b4c5b
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Thu Jan 20 21:40:53 2011 +0100
gt64xxx: set isa_mem_base during registration
isa_mem_base is computed from registers during reset, but due to QEMU
limitations some devices (e.g. VGA card) need to know it earlier when
they are registered.
Workaround this by setting the value during registration instead of
reset.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 7ec09df..923073b 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -1125,6 +1125,11 @@ static int gt64120_init(SysBusDevice *dev)
s = FROM_SYSBUS(GT64120State, dev);
+ /* FIXME: This value is computed from registers during reset, but some
+ devices (e.g. VGA card) need to know it when they are registered.
+ This also mean that changing the register to change the mapping
+ does not fully work. */
+ isa_mem_base = 0x10000000;
qemu_register_reset(gt64120_reset, s);
register_savevm(&dev->qdev, "GT64120 PCI Bus", 0, 1,
gt64120_save, gt64120_load, &s->pci);
commit 730986e4942188c5ec2b8752e3db47d09cb222b2
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Jan 20 16:04:52 2011 +0000
hw/pl190.c: Fix writing of default vector address
The PL190 implementation keeps the default vector address
in vect_addr[16], but we weren't using this for writes to
the DEFVECTADDR register. As a result of this fix the
default_addr structure member is unused and we can delete it.
Reported-by: Himanshu Chauhan <hschauhan at nulltrace.org>
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/pl190.c b/hw/pl190.c
index 17c279b..75f2ba1 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -21,7 +21,6 @@ typedef struct {
uint32_t soft_level;
uint32_t irq_enable;
uint32_t fiq_select;
- uint32_t default_addr;
uint8_t vect_control[16];
uint32_t vect_addr[PL190_NUM_PRIO];
/* Mask containing interrupts with higher priority than this one. */
@@ -186,7 +185,7 @@ static void pl190_write(void *opaque, target_phys_addr_t offset, uint32_t val)
s->priority = s->prev_prio[s->priority];
break;
case 13: /* DEFVECTADDR */
- s->default_addr = val;
+ s->vect_addr[16] = val;
break;
case 0xc0: /* ITCR */
if (val) {
@@ -252,7 +251,6 @@ static const VMStateDescription vmstate_pl190 = {
VMSTATE_UINT32(soft_level, pl190_state),
VMSTATE_UINT32(irq_enable, pl190_state),
VMSTATE_UINT32(fiq_select, pl190_state),
- VMSTATE_UINT32(default_addr, pl190_state),
VMSTATE_UINT8_ARRAY(vect_control, pl190_state, 16),
VMSTATE_UINT32_ARRAY(vect_addr, pl190_state, PL190_NUM_PRIO),
VMSTATE_UINT32_ARRAY(prio_mask, pl190_state, PL190_NUM_PRIO+1),
commit 5dbbda340533cd7d217dcf3ab904fb353598cbde
Merge: d788b57... e10990c...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Thu Jan 20 09:05:37 2011 -0600
Merge remote branch 'mst/for_anthony' into staging
commit d788b57051ee91aa39de67cff8d8e15953bc100c
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Mon Jan 17 19:29:33 2011 +0100
target-ppc: fix wrong NaN tests
Some tests in FPU emulation code were wrongly using float64_is_nan()
before commit 185698715dfb18c82ad2a5dbc169908602d43e81, and wrongly
using float64_is_quiet_nan() after. Fix them by using float64_is_any_nan()
instead.
Reviewed-by: Nathan Froyd <froydnj at codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index f9d6130..17e070a 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -546,7 +546,7 @@ uint32_t helper_compute_fprf (uint64_t arg, uint32_t set_fprf)
int ret;
farg.ll = arg;
isneg = float64_is_neg(farg.d);
- if (unlikely(float64_is_quiet_nan(farg.d))) {
+ if (unlikely(float64_is_any_nan(farg.d))) {
if (float64_is_signaling_nan(farg.d)) {
/* Signaling NaN: flags are undefined */
ret = 0x00;
@@ -1356,8 +1356,9 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
/* This is OK on x86 hosts */
farg1.d = (farg1.d * farg2.d) + farg3.d;
#endif
- if (likely(!float64_is_quiet_nan(farg1.d)))
+ if (likely(!float64_is_any_nan(farg1.d))) {
farg1.d = float64_chs(farg1.d);
+ }
}
return farg1.ll;
}
@@ -1402,8 +1403,9 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
/* This is OK on x86 hosts */
farg1.d = (farg1.d * farg2.d) - farg3.d;
#endif
- if (likely(!float64_is_quiet_nan(farg1.d)))
+ if (likely(!float64_is_any_nan(farg1.d))) {
farg1.d = float64_chs(farg1.d);
+ }
}
return farg1.ll;
}
@@ -1506,10 +1508,11 @@ uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg1.ll = arg1;
- if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && !float64_is_quiet_nan(farg1.d))
+ if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && !float64_is_any_nan(farg1.d)) {
return arg2;
- else
+ } else {
return arg3;
+ }
}
void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD)
@@ -1519,8 +1522,8 @@ void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_quiet_nan(farg1.d) ||
- float64_is_quiet_nan(farg2.d))) {
+ if (unlikely(float64_is_any_nan(farg1.d) ||
+ float64_is_any_nan(farg2.d))) {
ret = 0x01UL;
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x08UL;
@@ -1548,8 +1551,8 @@ void helper_fcmpo (uint64_t arg1, uint64_t arg2, uint32_t crfD)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_quiet_nan(farg1.d) ||
- float64_is_quiet_nan(farg2.d))) {
+ if (unlikely(float64_is_any_nan(farg1.d) ||
+ float64_is_any_nan(farg2.d))) {
ret = 0x01UL;
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x08UL;
@@ -3446,8 +3449,9 @@ uint32_t helper_efdctsi (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
return float64_to_int32(u.d, &env->vec_status);
}
@@ -3458,8 +3462,9 @@ uint32_t helper_efdctui (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
return float64_to_uint32(u.d, &env->vec_status);
}
@@ -3470,8 +3475,9 @@ uint32_t helper_efdctsiz (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
return float64_to_int32_round_to_zero(u.d, &env->vec_status);
}
@@ -3482,8 +3488,9 @@ uint64_t helper_efdctsidz (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
return float64_to_int64_round_to_zero(u.d, &env->vec_status);
}
@@ -3494,8 +3501,9 @@ uint32_t helper_efdctuiz (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
}
@@ -3506,8 +3514,9 @@ uint64_t helper_efdctuidz (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
}
@@ -3543,8 +3552,9 @@ uint32_t helper_efdctsf (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
u.d = float64_mul(u.d, tmp, &env->vec_status);
@@ -3558,8 +3568,9 @@ uint32_t helper_efdctuf (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
- if (unlikely(float64_is_quiet_nan(u.d)))
+ if (unlikely(float64_is_any_nan(u.d))) {
return 0;
+ }
tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
u.d = float64_mul(u.d, tmp, &env->vec_status);
commit 96912e39709e8455c013931513eebe8e6356eab4
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Mon Jan 17 19:29:33 2011 +0100
target-ppc: fix sNaN propagation
The current FPU code returns 0.0 if one of the operand is a
signaling NaN and the VXSNAN exception is disabled.
fload_invalid_op_excp() doesn't return a qNaN in case of a VXSNAN
exception as the operand should be propagated instead of a new
qNaN to be generated. Fix that by calling fload_invalid_op_excp()
only for the exception generation (if enabled), and use the softfloat
code to correctly compute the result.
Reviewed-by: Nathan Froyd <froydnj at codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 279f345..f9d6130 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -975,15 +975,16 @@ uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d))) {
- /* sNaN addition */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
- float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
+ if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
+ float64_is_neg(farg1.d) != float64_is_neg(farg2.d))) {
/* Magnitude subtraction of infinities */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d))) {
+ /* sNaN addition */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
}
@@ -998,15 +999,16 @@ uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d))) {
- /* sNaN subtraction */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
- float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
+ if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d) &&
+ float64_is_neg(farg1.d) == float64_is_neg(farg2.d))) {
/* Magnitude subtraction of infinities */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXISI);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d))) {
+ /* sNaN subtraction */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
}
@@ -1021,15 +1023,16 @@ uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d))) {
- /* sNaN multiplication */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
- (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
+ if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
+ (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d))) {
+ /* sNaN multiplication */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
}
@@ -1044,17 +1047,18 @@ uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d))) {
- /* sNaN division */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d))) {
+ if (unlikely(float64_is_infinity(farg1.d) && float64_is_infinity(farg2.d))) {
/* Division of infinity by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIDI);
} else if (unlikely(float64_is_zero(farg1.d) && float64_is_zero(farg2.d))) {
/* Division of zero by zero */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXZDZ);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d))) {
+ /* sNaN division */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
}
@@ -1232,16 +1236,17 @@ uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg2.ll = arg2;
farg3.ll = arg3;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d) ||
- float64_is_signaling_nan(farg3.d))) {
- /* sNaN operation */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
- (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
+ if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
+ (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d) ||
+ float64_is_signaling_nan(farg3.d))) {
+ /* sNaN operation */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1276,16 +1281,17 @@ uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg2.ll = arg2;
farg3.ll = arg3;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d) ||
- float64_is_signaling_nan(farg3.d))) {
- /* sNaN operation */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
+ if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
(float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d) ||
+ float64_is_signaling_nan(farg3.d))) {
+ /* sNaN operation */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1319,16 +1325,17 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg2.ll = arg2;
farg3.ll = arg3;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d) ||
- float64_is_signaling_nan(farg3.d))) {
- /* sNaN operation */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
- (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
+ if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
+ (float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d) ||
+ float64_is_signaling_nan(farg3.d))) {
+ /* sNaN operation */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1364,16 +1371,17 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg2.ll = arg2;
farg3.ll = arg3;
- if (unlikely(float64_is_signaling_nan(farg1.d) ||
- float64_is_signaling_nan(farg2.d) ||
- float64_is_signaling_nan(farg3.d))) {
- /* sNaN operation */
- farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
+ if (unlikely((float64_is_infinity(farg1.d) && float64_is_zero(farg2.d)) ||
(float64_is_zero(farg1.d) && float64_is_infinity(farg2.d)))) {
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
+ if (unlikely(float64_is_signaling_nan(farg1.d) ||
+ float64_is_signaling_nan(farg2.d) ||
+ float64_is_signaling_nan(farg3.d))) {
+ /* sNaN operation */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@@ -1409,11 +1417,11 @@ uint64_t helper_frsp (uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN square root */
- farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else {
- f32 = float64_to_float32(farg.d, &env->fp_status);
- farg.d = float32_to_float64(f32, &env->fp_status);
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
}
+ f32 = float64_to_float32(farg.d, &env->fp_status);
+ farg.d = float32_to_float64(f32, &env->fp_status);
+
return farg.ll;
}
@@ -1423,13 +1431,14 @@ uint64_t helper_fsqrt (uint64_t arg)
CPU_DoubleU farg;
farg.ll = arg;
- if (unlikely(float64_is_signaling_nan(farg.d))) {
- /* sNaN square root */
- farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
+ if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
/* Square root of a negative nonzero number */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
} else {
+ if (unlikely(float64_is_signaling_nan(farg.d))) {
+ /* sNaN square root */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg.d = float64_sqrt(farg.d, &env->fp_status);
}
return farg.ll;
@@ -1443,10 +1452,9 @@ uint64_t helper_fre (uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN reciprocal */
- farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else {
- farg.d = float64_div(float64_one, farg.d, &env->fp_status);
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
}
+ farg.d = float64_div(float64_one, farg.d, &env->fp_status);
return farg.d;
}
@@ -1459,12 +1467,12 @@ uint64_t helper_fres (uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN reciprocal */
- farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else {
- farg.d = float64_div(float64_one, farg.d, &env->fp_status);
- f32 = float64_to_float32(farg.d, &env->fp_status);
- farg.d = float32_to_float64(f32, &env->fp_status);
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
}
+ farg.d = float64_div(float64_one, farg.d, &env->fp_status);
+ f32 = float64_to_float32(farg.d, &env->fp_status);
+ farg.d = float32_to_float64(f32, &env->fp_status);
+
return farg.ll;
}
@@ -1475,13 +1483,14 @@ uint64_t helper_frsqrte (uint64_t arg)
float32 f32;
farg.ll = arg;
- if (unlikely(float64_is_signaling_nan(farg.d))) {
- /* sNaN reciprocal square root */
- farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
- } else if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
+ if (unlikely(float64_is_neg(farg.d) && !float64_is_zero(farg.d))) {
/* Reciprocal square root of a negative nonzero number */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSQRT);
} else {
+ if (unlikely(float64_is_signaling_nan(farg.d))) {
+ /* sNaN reciprocal square root */
+ fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
+ }
farg.d = float64_sqrt(farg.d, &env->fp_status);
farg.d = float64_div(float64_one, farg.d, &env->fp_status);
f32 = float64_to_float32(farg.d, &env->fp_status);
commit e10990c3f0c39e92ab5f74004b89a24fcc36fa14
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Thu Jan 20 15:57:49 2011 +0900
pci: use qemu_malloc() in pcibus_get_dev_path()
use qemu_malloc() instead of direct use of malloc().
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/pci.c b/hw/pci.c
index 1ffe428..b8f5385 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -2058,7 +2058,7 @@ static char *pcibus_get_dev_path(DeviceState *dev)
path_len = domain_len + slot_len * slot_depth;
/* Allocate memory, fill in the terminating null byte. */
- path = malloc(path_len + 1 /* For '\0' */);
+ path = qemu_malloc(path_len + 1 /* For '\0' */);
path[path_len] = '\0';
/* First field is the domain. */
commit e407bf13ba65163a8f8669e0157839bbefdb43b8
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Thu Jan 20 16:21:40 2011 +0900
msix: simplify write config
use pci_device_deassert_intx().
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/msix.c b/hw/msix.c
index e123082..daaf9b7 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -159,7 +159,6 @@ void msix_write_config(PCIDevice *dev, uint32_t addr,
{
unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET;
int vector;
- int i;
if (!range_covers_byte(addr, len, enable_pos)) {
return;
@@ -169,9 +168,7 @@ void msix_write_config(PCIDevice *dev, uint32_t addr,
return;
}
- for (i = 0; i < PCI_NUM_PINS; ++i) {
- qemu_set_irq(dev->irq[i], 0);
- }
+ pci_device_deassert_intx(dev);
if (msix_function_masked(dev)) {
return;
commit 59369b0816de3e76fa20204be5f6144de1ce8937
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Thu Jan 20 16:21:39 2011 +0900
msi: simplify write config a bit.
use pci_device_deassert_intx().
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/msi.c b/hw/msi.c
index f03f519..3dc3a24 100644
--- a/hw/msi.c
+++ b/hw/msi.c
@@ -255,7 +255,6 @@ void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len)
uint8_t log_max_vecs;
unsigned int vector;
uint32_t pending;
- int i;
if (!ranges_overlap(addr, len, dev->msi_cap, msi_cap_sizeof(flags))) {
return;
@@ -296,9 +295,7 @@ void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len)
* from using its INTx# pin (if implemented) to request
* service (MSI, MSI-X, and INTx# are mutually exclusive).
*/
- for (i = 0; i < PCI_NUM_PINS; ++i) {
- qemu_set_irq(dev->irq[i], 0);
- }
+ pci_device_deassert_intx(dev);
/*
* nr_vectors might be set bigger than capable. So clamp it.
commit 4c92325b5196ebd34886174a80d2f9fac35a004f
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Thu Jan 20 16:21:38 2011 +0900
pci: deassert intx on reset.
deassert intx on device reset.
So far pci_device_reset() is used for system reset.
In that case, interrupt controller is reset at the same time so that
all irq is are deasserted.
But now pci bus reset/flr is supported, and in that case irq needs to be
disabled explicitly.
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/pci.c b/hw/pci.c
index c77f6e9..1ffe428 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -137,6 +137,14 @@ static void pci_update_irq_status(PCIDevice *dev)
}
}
+void pci_device_deassert_intx(PCIDevice *dev)
+{
+ int i;
+ for (i = 0; i < PCI_NUM_PINS; ++i) {
+ qemu_set_irq(dev->irq[i], 0);
+ }
+}
+
/*
* This function is called on #RST and FLR.
* FLR if PCI_EXP_DEVCTL_BCR_FLR is set
@@ -152,6 +160,7 @@ void pci_device_reset(PCIDevice *dev)
dev->irq_state = 0;
pci_update_irq_status(dev);
+ pci_device_deassert_intx(dev);
/* Clear all writeable bits */
pci_word_test_and_clear_mask(dev->config + PCI_COMMAND,
pci_get_word(dev->wmask + PCI_COMMAND) |
diff --git a/hw/pci.h b/hw/pci.h
index bc8d5bb..0d2753f 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -264,6 +264,8 @@ void do_pci_info_print(Monitor *mon, const QObject *data);
void do_pci_info(Monitor *mon, QObject **ret_data);
void pci_bridge_update_mappings(PCIBus *b);
+void pci_device_deassert_intx(PCIDevice *dev);
+
static inline void
pci_set_byte(uint8_t *config, uint8_t val)
{
commit b2bf03a90ca3024213e354d3e0a6bc0cc8fc31e8
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Tue Jan 18 19:11:33 2011 +0300
pxa2xx_lcd: restore updating of display
Recently PXA2xx lcd have stopped to be updated incrementally (picture
frozen). This patch fixes that by passing non min/max x/y, but rather
(correctly) x/y and w/h.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c
index 1f2211a..5b2b07e 100644
--- a/hw/pxa2xx_lcd.c
+++ b/hw/pxa2xx_lcd.c
@@ -796,9 +796,9 @@ static void pxa2xx_update_display(void *opaque)
if (miny >= 0) {
if (s->orientation)
- dpy_update(s->ds, miny, 0, maxy, s->xres);
+ dpy_update(s->ds, miny, 0, maxy - miny, s->xres);
else
- dpy_update(s->ds, 0, miny, s->xres, maxy);
+ dpy_update(s->ds, 0, miny, s->xres, maxy - miny);
}
pxa2xx_lcdc_int_update(s);
commit f69866ea32f4e1f54bc14e3b4fa3d7e79754a205
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Thu Jan 13 18:37:12 2011 +0300
pxa2xx: fix vmstate_pxa2xx_i2c
vmstate_pxa2xx_i2c incorrectly recursed to itself instead of going
to store slave device. Fix that stop stop qemu from segfaulting
during savevm for pxa2xx-based devices.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index ab524a7..6e72a5c 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1476,7 +1476,7 @@ static const VMStateDescription vmstate_pxa2xx_i2c = {
VMSTATE_UINT8(ibmr, PXA2xxI2CState),
VMSTATE_UINT8(data, PXA2xxI2CState),
VMSTATE_STRUCT_POINTER(slave, PXA2xxI2CState,
- vmstate_pxa2xx_i2c, PXA2xxI2CSlaveState *),
+ vmstate_pxa2xx_i2c_slave, PXA2xxI2CSlaveState *),
VMSTATE_END_OF_LIST()
}
};
commit aa9438d9f8a19258514c5cc238d2494a2572ff58
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Thu Jan 13 18:37:11 2011 +0300
scoop: fix access to registers from second instance
Second instance of scoop contains registers shifted to 0x40 from the start
of the page. Instead of messing with register mapping, just limit register
address to 0x00..0x3f.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/zaurus.c b/hw/zaurus.c
index 54ec3f0..36be94a 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -70,7 +70,7 @@ static uint32_t scoop_readb(void *opaque, target_phys_addr_t addr)
{
ScoopInfo *s = (ScoopInfo *) opaque;
- switch (addr) {
+ switch (addr & 0x3f) {
case SCOOP_MCR:
return s->mcr;
case SCOOP_CDR:
@@ -104,7 +104,7 @@ static void scoop_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
ScoopInfo *s = (ScoopInfo *) opaque;
value &= 0xffff;
- switch (addr) {
+ switch (addr & 0x3f) {
case SCOOP_MCR:
s->mcr = value;
break;
commit f75d216a80977da3435f507fa6bae0821a5d9076
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Thu Jan 13 18:37:10 2011 +0300
mainstone: fix name of the allocated memory for roms
Mainstone board has two flash chips (emulated by two ram regions), however
currently code tries to allocate them with the same name, which fails.
Fix that to make mainstone emulation work again.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/mainstone.c b/hw/mainstone.c
index efa2959..58e3f86 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -106,7 +106,8 @@ static void mainstone_common_init(ram_addr_t ram_size,
}
if (!pflash_cfi01_register(mainstone_flash_base[i],
- qemu_ram_alloc(NULL, "mainstone.flash",
+ qemu_ram_alloc(NULL, i ? "mainstone.flash1" :
+ "mainstone.flash0",
MAINSTONE_FLASH),
dinfo->bdrv, sector_len,
MAINSTONE_FLASH / sector_len, 4, 0, 0, 0, 0,
commit 2a3c633c1eb8692716220195b6d3fe78b7e411d0
Author: Fred Boiteux <fblistes+qemu at free.fr>
Date: Sun Jan 9 14:24:59 2011 +0100
add bepo (french dvorak) keyboard layout
I'm using the Qemu program with VNC I/O, and I had some problems with
my keyboard layout, so I've prepared a definition to be included in
Qemu, built from Xorg description.
Signed-off-by: Frédéric Boiteux <fboiteux at free.fr>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/pc-bios/keymaps/bepo b/pc-bios/keymaps/bepo
new file mode 100644
index 0000000..d40041a
--- /dev/null
+++ b/pc-bios/keymaps/bepo
@@ -0,0 +1,333 @@
+include common
+
+# Bépo : Improved ergonomic french keymap using Dvorak method.
+# Built by community on 'Dvorak Fr / Bépo' :
+# see http://www.clavier-dvorak.org/wiki/ to join and help.
+#
+# Bépo layout (1.0rc2 version) for a pc105 keyboard (french) :
+# ââââââ
+# â S Aâ S = Shift, A = AltGr + Shift
+# â s aâ s = normal, a = AltGr
+# ââââââ
+#
+# âââââââ¬ââââââ¬ââââââ¬ââââââ¬ââââââ¬ââââââ¬ââââââ¬ââââââ¬ââââââ¬ââââââ¬ââââââ¬ââââââ¬ââââââ²ââââââââââ
+# â # ¶ â 1 â â 2 â â 3 â â 4 ⤠â 5 ⥠â 6 â 7 ¬ â 8 ¼ â 9 ½ â 0 ¾ â ° â² â ` â³ â â« Retourâ
+# â $ â â " â â « < â » > â ( [ â ) ] â @ ^ â + ± â - â â / ÷ â * à â = â â % â° â arrièreâ
+# â¢ââââââ·ââ±ââââ´ââ¬ââââ´ââ¬ââââ´ââ¬ââââ´ââ¬ââââ´ââ¬ââââ´ââ¬ââââ´ââ¬ââââ´ââ¬ââââ´ââ¬ââââ´ââ¬ââââ´ââ¬ââââºââ³ââââââââ«
+# â â B ¦ â Ã Ë â P § â O Å â à ` â ! â V â D à â L â J IJ â Z Æ â W âEntrée â
+# âTab â¹ â b | â é Ë â p & â o Å â è ` â Ë Â¡ â v Ë â d ð â l / â j ij â z É â w Ì â â â
+# â£ââââââââ»â±âââââ´â¬âââââ´â¬âââââ´â¬âââââ´â¬âââââ´â¬âââââ´â¬âââââ´â¬âââââ´â¬âââââ´â¬âââââ´â¬âââââ´â¬âââââºâ â
+# â â A à â U à â I Ë â E ¤ â ; Ì â C Å¿ â T à â S Ạâ R ⢠â N â M º â à , â â
+# âMaj ⬠â a æ â u ù â i Ì â e ⬠â , â â c © â t þ â s à â r ® â n Ë â m ¯ â ç ¸ â â
+# â£ââââââââ³â¹âââââ¬â´âââââ¬â´âââââ¬â´âââââ¬â´âââââ¬â´âââââ¬â´âââââ¬â´âââââ¬â´âââââ¬â´âââââ¬â´âââââ²â·ââââââ»âââââââ«
+# â â à â à â Y â â X â â : · â K â ? Ì â Q Ì£ â G â H â¡ â F ª â â
+# âShift â§â ê / â à \ â y { â x } â . ⦠â k ~ â ' ¿ â q Ë â g µ â h â â f Ë âShift ⧠â
+# â£ââââââââââââââ·ââ³ââââ·ââââ±ââ´ââââââ´ââââââ´ââââââ´ââââââ´ââââââ´ââââ²ââ·ââââââââââââ»ââ³ââââââââ³ââââ
+# â â â â Espace inséc. Espace inséc. fin â â â â
+# âCtrl âMeta âAlt â ⣠(Espace) _ ⣠âAltGr â®âMenu âCtrl â
+# âââââââââ»ââââââââ»ââââââââ¹ââââââââââââââââââââââââââââââââââââºââââââââ»ââââââââ»ââââââââ
+
+
+# First row
+## keycode 41 = dollar numbersign U+2013 U+00b6
+dollar 0x29
+numbersign 0x29 shift
+U2013 0x29 altgr
+U00b6 0x29 shift altgr
+
+## keycode 2 = +quotedbl +one U+2014 U+201e
+quotedbl 0x2
+one 0x2 shift
+U2014 0x2 altgr
+U201e 0x2 shift altgr
+
+## keycode 3 = +guillemotleft +two less U+201c
+guillemotleft 0x3
+two 0x3 shift
+less 0x3 altgr
+U201c 0x3 shift altgr
+
+## keycode 4 = +guillemotright +three greater U+201d
+guillemotright 0x4
+three 0x4 shift
+greater 0x4 altgr
+U201d 0x4 shift altgr
+
+## keycode 5 = +parenleft +four bracketleft U+2264
+parenleft 0x5
+four 0x5 shift
+bracketleft 0x5 altgr
+U2264 0x5 shift altgr
+
+## keycode 6 = +parenright +five bracketright U+2265
+parenright 0x6
+five 0x6 shift
+bracketright 0x6 altgr
+U2265 0x6 shift altgr
+
+## keycode 7 = +at +six asciicircum
+at 0x7
+six 0x7 shift
+asciicircum 0x7 altgr
+
+## keycode 8 = +plus +seven U+00b1 U+00ac
+plus 0x8
+seven 0x8 shift
+U00b1 0x8 altgr
+U00ac 0x8 shift altgr
+
+## keycode 9 = +minus +eight U+2212 U+00bc
+minus 0x9
+eight 0x9 shift
+U2212 0x9 altgr
+U00bc 0x9 shift altgr
+
+## keycode 10 = +slash +nine U+00f7 U+00bd
+slash 0xa
+nine 0xa shift
+U00f7 0xa altgr
+U00bd 0xa shift altgr
+
+## keycode 11 = +asterisk +zero U+00d7 U+00be
+asterisk 0xb
+zero 0xb shift
+U00d7 0xb altgr
+U00be 0xb shift altgr
+
+## keycode 12 = equal U+00b0 U+2260 U+2032
+equal 0xc
+U00b0 0xc shift
+U2260 0xc altgr
+U2032 0xc shift altgr
+
+## keycode 13 = percent grave U+2030 U+2033
+percent 0xd
+grave 0xd shift
+U2030 0xd altgr
+U2033 0xd shift altgr
+
+
+# Second row
+
+# simplified letter definitions notation :
+## keycode 16 = b
+b 0x10 addupper
+## keycode 18 = p
+p 0x12 addupper
+## keycode 19 = o
+o 0x13 addupper
+## keycode 22 = v
+v 0x16 addupper
+## keycode 23 = d
+d 0x17 addupper
+## keycode 24 = l
+l 0x18 addupper
+## keycode 25 = j
+j 0x19 addupper
+## keycode 26 = z
+z 0x1a addupper
+## keycode 27 = w
+w 0x1b addupper
+
+# then, add specific definitions
+## AltGr keycode 16 = bar
+bar 0x10 altgr
+## Shift AltGr keycode 16 = brokenbar
+brokenbar 0x10 shift altgr
+
+## keycode 17 = +eacute +Eacute dead_acute
+eacute 0x11
+Eacute 0x11 shift
+dead_acute 0x11 altgr
+
+## AltGr keycode 18 = ampersand
+ampersand 0x12 altgr
+## Shift AltGr keycode 18 = U+00a7
+U00a7 0x12 shift altgr
+
+## AltGr keycode 19 = +U+0153
+U+0153 0x13 altgr
+## Shift AltGr keycode 19 = +U+0152
+U+0152 0x13 shift altgr
+
+## keycode 20 = +egrave +Egrave dead_grave grave # no Metaâ¯!
+egrave 0x14
+Egrave 0x14 shift
+dead_grave 0x14 altgr
+
+## keycode 21 = dead_circumflex exclam exclamdown
+dead_circumflex 0x15
+exclam 0x15 shift
+exclamdown 0x15 altgr
+
+## AltGr keycode 22 = dead_caron
+dead_caron 0x16 altgr
+
+## AltGr keycode 23 = eth
+eth 0x17 altgr
+## Shift AltGr keycode 23 = ETH
+ETH 0x17 shift altgr
+
+## AltGr keycode 25 = +U+0133
+U+0133 0x19 altgr
+## Shift AltGr keycode 25 = +U+0132
+U+0132 0x19 shift altgr
+
+## AltGr keycode 26 = +U+0259
+U+0259 0x1a altgr
+## Shift AltGr keycode 26 = +U+018f
+U+018f 0x1a shift altgr
+
+
+
+# Third row
+
+# simplified letter definitions notation :
+## keycode 30 = a
+a 0x1e addupper
+## keycode 31 = u
+u 0x1f addupper
+## keycode 32 = i
+i 0x20 addupper
+## keycode 33 = e
+e 0x21 addupper
+## keycode 35 = c
+c 0x23 addupper
+## keycode 36 = t
+t 0x24 addupper
+## keycode 37 = s
+s 0x25 addupper
+## keycode 38 = r
+r 0x26 addupper
+## keycode 39 = n
+n 0x27 addupper
+## keycode 40 = m
+m 0x28 addupper
+
+# then, add specific definitions
+## AltGr keycode 30 = +ae
+ae 0x1e altgr
+## Shift AltGr keycode 30 = +AE
+AE 0x1e shift altgr
+
+## AltGr keycode 31 = +ugrave
+ugrave 0x1f altgr
+## Shift AltGr keycode 31 = +Ugrave
+Ugrave 0x1f shift altgr
+
+## AltGr keycode 32 = dead_diaeresis
+dead_diaeresis 0x20 altgr
+
+
+## AltGr keycode 33 = U+20ac
+U20ac 0x21 altgr
+
+## keycode 34 = comma semicolon U+2019 +U+031b
+comma 0x22
+semicolon 0x22 shift
+U2019 0x22 altgr
+U+031b 0x22 shift altgr
+
+## AltGr keycode 35 = copyright
+copyright 0x23 altgr
+## Shift AltGr keycode 35 = U+017f
+U017f 0x23 shift altgr
+
+## AltGr keycode 36 = +thorn
+thorn 0x24 altgr
+## Shift AltGr keycode 36 = +THORN
+THORN 0x24 shift altgr
+
+## AltGr keycode 37 = +ssharp
+ssharp 0x25 altgr
+## Shift AltGr keycode 37 = U+1e9e
+U1e9e 0x25 shift altgr
+
+## AltGr keycode 38 = registered
+registered 0x26 altgr
+## Shift AltGr keycode 38 = U+2122
+U2122 0x26 shift altgr
+
+## AltGr keycode 39 = dead_tilde
+dead_tilde 0x27 altgr
+
+## Shift AltGr keycode 40 = masculine
+masculine 0x28 shift altgr
+
+## keycode 43 = +ccedilla +Ccedilla dead_cedilla
+ccedilla 0x2b
+Ccedilla 0x2b shift
+dead_cedilla 0x2b altgr
+
+
+# Fourth row
+
+# simplified letter definitions notation :
+## keycode 45 = y
+y 0x2d addupper
+## keycode 46 = x
+x 0x2e addupper
+## keycode 48 = k
+k 0x30 addupper
+## keycode 50 = q
+q 0x32 addupper
+## keycode 51 = g
+g 0x33 addupper
+## keycode 52 = h
+h 0x34 addupper
+## keycode 53 = f
+f 0x35 addupper
+
+# then, add specific definitions
+## keycode 86 = +ecircumflex +Ecircumflex slash slash
+ecircumflex 0x56
+Ecircumflex 0x56 shift
+
+## keycode 44 = +agrave +Agrave backslash
+agrave 0x2c
+Agrave 0x2c shift
+backslash 0x2c altgr
+
+## AltGr keycode 45 = braceleft
+braceleft 0x2d altgr
+## Shift AltGr keycode 45 = U+2018
+U2018 0x2d shift altgr
+
+## AltGr keycode 46 = braceright
+braceright 0x2e altgr
+
+## keycode 47 = period colon U+2026 periodcentered
+period 0x2f
+colon 0x2f shift
+U2026 0x2f altgr
+periodcentered 0x2f shift altgr
+
+## AltGr keycode 48 = asciitilde
+asciitilde 0x30 altgr
+## Shift AltGr keycode 48 = U+2328
+U2328 0x30 shift altgr
+
+## keycode 49 = apostrophe question questiondown +U+0309
+apostrophe 0x31
+question 0x31 shift
+questiondown 0x31 altgr
+U+0309 0x31 shift altgr
+
+## AltGr keycode 51 = mu
+mu 0x33 altgr
+
+## AltGr keycode 52 = U+2020
+U2020 0x34 altgr
+## Shift AltGr keycode 52 = U+2021
+U2021 0x34 shift altgr
+
+## Shift AltGr keycode 53 = ordfeminine
+ordfeminine 0x35 shift altgr
+
+
+
+## keycode 57 = space nobreakspace underscore U+202f
+space 0x39
+nobreakspace 0x39 shift
+underscore 0x39 altgr
+U202f 0x39 shift altgr
commit 3ac59434c771ed65ea76f64589807d88c77cf3f5
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Dec 23 17:19:58 2010 +0000
stc91c111: Implement save/restore
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/smc91c111.c b/hw/smc91c111.c
index fc714d7..dafea5c 100644
--- a/hw/smc91c111.c
+++ b/hw/smc91c111.c
@@ -46,6 +46,35 @@ typedef struct {
int mmio_index;
} smc91c111_state;
+static const VMStateDescription vmstate_smc91c111 = {
+ .name = "smc91c111",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT16(tcr, smc91c111_state),
+ VMSTATE_UINT16(rcr, smc91c111_state),
+ VMSTATE_UINT16(cr, smc91c111_state),
+ VMSTATE_UINT16(ctr, smc91c111_state),
+ VMSTATE_UINT16(gpr, smc91c111_state),
+ VMSTATE_UINT16(ptr, smc91c111_state),
+ VMSTATE_UINT16(ercv, smc91c111_state),
+ VMSTATE_INT32(bank, smc91c111_state),
+ VMSTATE_INT32(packet_num, smc91c111_state),
+ VMSTATE_INT32(tx_alloc, smc91c111_state),
+ VMSTATE_INT32(allocated, smc91c111_state),
+ VMSTATE_INT32(tx_fifo_len, smc91c111_state),
+ VMSTATE_INT32_ARRAY(tx_fifo, smc91c111_state, NUM_PACKETS),
+ VMSTATE_INT32(rx_fifo_len, smc91c111_state),
+ VMSTATE_INT32_ARRAY(rx_fifo, smc91c111_state, NUM_PACKETS),
+ VMSTATE_INT32(tx_fifo_done_len, smc91c111_state),
+ VMSTATE_INT32_ARRAY(tx_fifo_done, smc91c111_state, NUM_PACKETS),
+ VMSTATE_BUFFER_UNSAFE(data, smc91c111_state, 0, NUM_PACKETS * 2048),
+ VMSTATE_UINT8(int_level, smc91c111_state),
+ VMSTATE_UINT8(int_mask, smc91c111_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
#define RCR_SOFT_RST 0x8000
#define RCR_STRIP_CRC 0x0200
#define RCR_RXEN 0x0100
@@ -738,6 +767,7 @@ static SysBusDeviceInfo smc91c111_info = {
.init = smc91c111_init1,
.qdev.name = "smc91c111",
.qdev.size = sizeof(smc91c111_state),
+ .qdev.vmsd = &vmstate_smc91c111,
.qdev.props = (Property[]) {
DEFINE_NIC_PROPERTIES(smc91c111_state, conf),
DEFINE_PROP_END_OF_LIST(),
commit ff1758533c04ad8e7effc97627f5550b422e4de8
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Dec 23 17:19:57 2010 +0000
pl080: Implement save/restore
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/pl080.c b/hw/pl080.c
index 1a3e06c..901f04a 100644
--- a/hw/pl080.c
+++ b/hw/pl080.c
@@ -52,6 +52,43 @@ typedef struct {
qemu_irq irq;
} pl080_state;
+static const VMStateDescription vmstate_pl080_channel = {
+ .name = "pl080_channel",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(src, pl080_channel),
+ VMSTATE_UINT32(dest, pl080_channel),
+ VMSTATE_UINT32(lli, pl080_channel),
+ VMSTATE_UINT32(ctrl, pl080_channel),
+ VMSTATE_UINT32(conf, pl080_channel),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_pl080 = {
+ .name = "pl080",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(tc_int, pl080_state),
+ VMSTATE_UINT8(tc_mask, pl080_state),
+ VMSTATE_UINT8(err_int, pl080_state),
+ VMSTATE_UINT8(err_mask, pl080_state),
+ VMSTATE_UINT32(conf, pl080_state),
+ VMSTATE_UINT32(sync, pl080_state),
+ VMSTATE_UINT32(req_single, pl080_state),
+ VMSTATE_UINT32(req_burst, pl080_state),
+ VMSTATE_UINT8(tc_int, pl080_state),
+ VMSTATE_UINT8(tc_int, pl080_state),
+ VMSTATE_UINT8(tc_int, pl080_state),
+ VMSTATE_STRUCT_ARRAY(chan, pl080_state, PL080_MAX_CHANNELS,
+ 1, vmstate_pl080_channel, pl080_channel),
+ VMSTATE_INT32(running, pl080_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const unsigned char pl080_id[] =
{ 0x80, 0x10, 0x04, 0x0a, 0x0d, 0xf0, 0x05, 0xb1 };
@@ -330,7 +367,6 @@ static int pl08x_init(SysBusDevice *dev, int nchannels)
sysbus_init_mmio(dev, 0x1000, iomemtype);
sysbus_init_irq(dev, &s->irq);
s->nchannels = nchannels;
- /* ??? Save/restore. */
return 0;
}
@@ -344,12 +380,28 @@ static int pl081_init(SysBusDevice *dev)
return pl08x_init(dev, 2);
}
+static SysBusDeviceInfo pl080_info = {
+ .init = pl080_init,
+ .qdev.name = "pl080",
+ .qdev.size = sizeof(pl080_state),
+ .qdev.vmsd = &vmstate_pl080,
+ .qdev.no_user = 1,
+};
+
+static SysBusDeviceInfo pl081_info = {
+ .init = pl081_init,
+ .qdev.name = "pl081",
+ .qdev.size = sizeof(pl080_state),
+ .qdev.vmsd = &vmstate_pl080,
+ .qdev.no_user = 1,
+};
+
/* The PL080 and PL081 are the same except for the number of channels
they implement (8 and 2 respectively). */
static void pl080_register_devices(void)
{
- sysbus_register_dev("pl080", sizeof(pl080_state), pl080_init);
- sysbus_register_dev("pl081", sizeof(pl080_state), pl081_init);
+ sysbus_register_withprop(&pl080_info);
+ sysbus_register_withprop(&pl081_info);
}
device_init(pl080_register_devices)
commit 8c60d0652ead554516125960b5e918cca2621399
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Dec 23 17:19:56 2010 +0000
pl110: Implement save/restore
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/pl110.c b/hw/pl110.c
index a4adb63..06d2dfa 100644
--- a/hw/pl110.c
+++ b/hw/pl110.c
@@ -48,6 +48,28 @@ typedef struct {
qemu_irq irq;
} pl110_state;
+static const VMStateDescription vmstate_pl110 = {
+ .name = "pl110",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_INT32(versatile, pl110_state),
+ VMSTATE_UINT32_ARRAY(timing, pl110_state, 4),
+ VMSTATE_UINT32(cr, pl110_state),
+ VMSTATE_UINT32(upbase, pl110_state),
+ VMSTATE_UINT32(lpbase, pl110_state),
+ VMSTATE_UINT32(int_status, pl110_state),
+ VMSTATE_UINT32(int_mask, pl110_state),
+ VMSTATE_INT32(cols, pl110_state),
+ VMSTATE_INT32(rows, pl110_state),
+ VMSTATE_UINT32(bpp, pl110_state),
+ VMSTATE_INT32(invalidate, pl110_state),
+ VMSTATE_UINT32_ARRAY(pallette, pl110_state, 256),
+ VMSTATE_UINT32_ARRAY(raw_pallette, pl110_state, 128),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const unsigned char pl110_id[] =
{ 0x10, 0x11, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
@@ -365,7 +387,6 @@ static int pl110_init(SysBusDevice *dev)
s->ds = graphic_console_init(pl110_update_display,
pl110_invalidate_display,
NULL, NULL, s);
- /* ??? Save/restore. */
return 0;
}
@@ -376,11 +397,26 @@ static int pl110_versatile_init(SysBusDevice *dev)
return pl110_init(dev);
}
+static SysBusDeviceInfo pl110_info = {
+ .init = pl110_init,
+ .qdev.name = "pl110",
+ .qdev.size = sizeof(pl110_state),
+ .qdev.vmsd = &vmstate_pl110,
+ .qdev.no_user = 1,
+};
+
+static SysBusDeviceInfo pl110_versatile_info = {
+ .init = pl110_versatile_init,
+ .qdev.name = "pl110_versatile",
+ .qdev.size = sizeof(pl110_state),
+ .qdev.vmsd = &vmstate_pl110,
+ .qdev.no_user = 1,
+};
+
static void pl110_register_devices(void)
{
- sysbus_register_dev("pl110", sizeof(pl110_state), pl110_init);
- sysbus_register_dev("pl110_versatile", sizeof(pl110_state),
- pl110_versatile_init);
+ sysbus_register_withprop(&pl110_info);
+ sysbus_register_withprop(&pl110_versatile_info);
}
device_init(pl110_register_devices)
commit 0dc5595c2c25ce6eb8eeb7704630b76348a53562
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Dec 23 17:19:55 2010 +0000
pl031: Implement save/restore
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/pl031.c b/hw/pl031.c
index e3700c1..c488f69 100644
--- a/hw/pl031.c
+++ b/hw/pl031.c
@@ -44,6 +44,21 @@ typedef struct {
uint32_t is;
} pl031_state;
+static const VMStateDescription vmstate_pl031 = {
+ .name = "pl031",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(tick_offset, pl031_state),
+ VMSTATE_UINT32(mr, pl031_state),
+ VMSTATE_UINT32(lr, pl031_state),
+ VMSTATE_UINT32(cr, pl031_state),
+ VMSTATE_UINT32(im, pl031_state),
+ VMSTATE_UINT32(is, pl031_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const unsigned char pl031_id[] = {
0x31, 0x10, 0x14, 0x00, /* Device ID */
0x0d, 0xf0, 0x05, 0xb1 /* Cell ID */
@@ -206,9 +221,17 @@ static int pl031_init(SysBusDevice *dev)
return 0;
}
+static SysBusDeviceInfo pl031_info = {
+ .init = pl031_init,
+ .qdev.name = "pl031",
+ .qdev.size = sizeof(pl031_state),
+ .qdev.vmsd = &vmstate_pl031,
+ .qdev.no_user = 1,
+};
+
static void pl031_register_devices(void)
{
- sysbus_register_dev("pl031", sizeof(pl031_state), pl031_init);
+ sysbus_register_withprop(&pl031_info);
}
device_init(pl031_register_devices)
commit d6ac172a84ba0d3ced0250bafbd63e36aed34378
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Dec 23 17:19:54 2010 +0000
pl050: Implement save/restore
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/pl050.c b/hw/pl050.c
index 0573839..b155cc0 100644
--- a/hw/pl050.c
+++ b/hw/pl050.c
@@ -21,6 +21,20 @@ typedef struct {
int is_mouse;
} pl050_state;
+static const VMStateDescription vmstate_pl050 = {
+ .name = "pl050",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(cr, pl050_state),
+ VMSTATE_UINT32(clk, pl050_state),
+ VMSTATE_UINT32(last, pl050_state),
+ VMSTATE_INT32(pending, pl050_state),
+ VMSTATE_INT32(is_mouse, pl050_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
#define PL050_TXEMPTY (1 << 6)
#define PL050_TXBUSY (1 << 5)
#define PL050_RXFULL (1 << 4)
@@ -137,7 +151,6 @@ static int pl050_init(SysBusDevice *dev, int is_mouse)
s->dev = ps2_mouse_init(pl050_update, s);
else
s->dev = ps2_kbd_init(pl050_update, s);
- /* ??? Save/restore. */
return 0;
}
@@ -151,12 +164,24 @@ static int pl050_init_mouse(SysBusDevice *dev)
return pl050_init(dev, 1);
}
+static SysBusDeviceInfo pl050_kbd_info = {
+ .init = pl050_init_keyboard,
+ .qdev.name = "pl050_keyboard",
+ .qdev.size = sizeof(pl050_state),
+ .qdev.vmsd = &vmstate_pl050,
+};
+
+static SysBusDeviceInfo pl050_mouse_info = {
+ .init = pl050_init_mouse,
+ .qdev.name = "pl050_mouse",
+ .qdev.size = sizeof(pl050_state),
+ .qdev.vmsd = &vmstate_pl050,
+};
+
static void pl050_register_devices(void)
{
- sysbus_register_dev("pl050_keyboard", sizeof(pl050_state),
- pl050_init_keyboard);
- sysbus_register_dev("pl050_mouse", sizeof(pl050_state),
- pl050_init_mouse);
+ sysbus_register_withprop(&pl050_kbd_info);
+ sysbus_register_withprop(&pl050_mouse_info);
}
device_init(pl050_register_devices)
commit b5ad0ae767b633305562150734c17bf430ccc045
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Dec 23 17:19:53 2010 +0000
arm_sysctl: Implement save/restore
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/arm_sysctl.c b/hw/arm_sysctl.c
index bd0664f..d8b062c 100644
--- a/hw/arm_sysctl.c
+++ b/hw/arm_sysctl.c
@@ -28,6 +28,22 @@ typedef struct {
uint32_t proc_id;
} arm_sysctl_state;
+static const VMStateDescription vmstate_arm_sysctl = {
+ .name = "realview_sysctl",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(leds, arm_sysctl_state),
+ VMSTATE_UINT16(lockval, arm_sysctl_state),
+ VMSTATE_UINT32(cfgdata1, arm_sysctl_state),
+ VMSTATE_UINT32(cfgdata2, arm_sysctl_state),
+ VMSTATE_UINT32(flags, arm_sysctl_state),
+ VMSTATE_UINT32(nvflags, arm_sysctl_state),
+ VMSTATE_UINT32(resetlevel, arm_sysctl_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static void arm_sysctl_reset(DeviceState *d)
{
arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, sysbus_from_qdev(d));
@@ -231,6 +247,7 @@ static SysBusDeviceInfo arm_sysctl_info = {
.init = arm_sysctl_init1,
.qdev.name = "realview_sysctl",
.qdev.size = sizeof(arm_sysctl_state),
+ .qdev.vmsd = &vmstate_arm_sysctl,
.qdev.reset = arm_sysctl_reset,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT32("sys_id", arm_sysctl_state, sys_id, 0),
commit a796d0acbbc6f3c0355b142c0a76c547e825c2ef
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Dec 23 17:19:52 2010 +0000
vpb_sic: Implement save/restore
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index be758e4..9f1bfcf 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -30,6 +30,18 @@ typedef struct vpb_sic_state
int irq;
} vpb_sic_state;
+static const VMStateDescription vmstate_vpb_sic = {
+ .name = "versatilepb_sic",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(level, vpb_sic_state),
+ VMSTATE_UINT32(mask, vpb_sic_state),
+ VMSTATE_UINT32(pic_enable, vpb_sic_state),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static void vpb_sic_update(vpb_sic_state *s)
{
uint32_t flags;
@@ -146,7 +158,6 @@ static int vpb_sic_init(SysBusDevice *dev)
vpb_sic_writefn, s,
DEVICE_NATIVE_ENDIAN);
sysbus_init_mmio(dev, 0x1000, iomemtype);
- /* ??? Save/restore. */
return 0;
}
@@ -335,10 +346,17 @@ static void versatile_machine_init(void)
machine_init(versatile_machine_init);
+static SysBusDeviceInfo vpb_sic_info = {
+ .init = vpb_sic_init,
+ .qdev.name = "versatilepb_sic",
+ .qdev.size = sizeof(vpb_sic_state),
+ .qdev.vmsd = &vmstate_vpb_sic,
+ .qdev.no_user = 1,
+};
+
static void versatilepb_register_devices(void)
{
- sysbus_register_dev("versatilepb_sic", sizeof(vpb_sic_state),
- vpb_sic_init);
+ sysbus_register_withprop(&vpb_sic_info);
}
device_init(versatilepb_register_devices)
commit ac49d7500110e7380e8b4ea91b3d05a2cfe33448
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Dec 23 17:19:51 2010 +0000
pl190: Implement save/restore
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/pl190.c b/hw/pl190.c
index e04e6c1..17c279b 100644
--- a/hw/pl190.c
+++ b/hw/pl190.c
@@ -212,8 +212,9 @@ static CPUWriteMemoryFunc * const pl190_writefn[] = {
pl190_write
};
-static void pl190_reset(pl190_state *s)
+static void pl190_reset(DeviceState *d)
{
+ pl190_state *s = DO_UPCAST(pl190_state, busdev.qdev, d);
int i;
for (i = 0; i < 16; i++)
@@ -239,14 +240,41 @@ static int pl190_init(SysBusDevice *dev)
qdev_init_gpio_in(&dev->qdev, pl190_set_irq, 32);
sysbus_init_irq(dev, &s->irq);
sysbus_init_irq(dev, &s->fiq);
- pl190_reset(s);
- /* ??? Save/restore. */
return 0;
}
+static const VMStateDescription vmstate_pl190 = {
+ .name = "pl190",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(level, pl190_state),
+ VMSTATE_UINT32(soft_level, pl190_state),
+ VMSTATE_UINT32(irq_enable, pl190_state),
+ VMSTATE_UINT32(fiq_select, pl190_state),
+ VMSTATE_UINT32(default_addr, pl190_state),
+ VMSTATE_UINT8_ARRAY(vect_control, pl190_state, 16),
+ VMSTATE_UINT32_ARRAY(vect_addr, pl190_state, PL190_NUM_PRIO),
+ VMSTATE_UINT32_ARRAY(prio_mask, pl190_state, PL190_NUM_PRIO+1),
+ VMSTATE_INT32(protected, pl190_state),
+ VMSTATE_INT32(priority, pl190_state),
+ VMSTATE_INT32_ARRAY(prev_prio, pl190_state, PL190_NUM_PRIO),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static SysBusDeviceInfo pl190_info = {
+ .init = pl190_init,
+ .qdev.name = "pl190",
+ .qdev.size = sizeof(pl190_state),
+ .qdev.vmsd = &vmstate_pl190,
+ .qdev.reset = pl190_reset,
+ .qdev.no_user = 1,
+};
+
static void pl190_register_devices(void)
{
- sysbus_register_dev("pl190", sizeof(pl190_state), pl190_init);
+ sysbus_register_withprop(&pl190_info);
}
device_init(pl190_register_devices)
commit c2dd2a2352ebd51911460e65453455d489bea564
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Wed Jan 19 23:10:40 2011 +0100
gt64xxx: qdev conversion
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 14c6ad3..7ec09df 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -223,16 +223,14 @@
#define GT_PCI0_HICMASK (0xca4 >> 2)
#define GT_PCI1_SERR1MASK (0xca8 >> 2)
-
-typedef PCIHostState GT64120PCIState;
-
#define PCI_MAPPING_ENTRY(regname) \
target_phys_addr_t regname ##_start; \
target_phys_addr_t regname ##_length; \
int regname ##_handle
typedef struct GT64120State {
- GT64120PCIState *pci;
+ SysBusDevice busdev;
+ PCIHostState pci;
uint32_t regs[GT_REGS];
PCI_MAPPING_ENTRY(PCI0IO);
PCI_MAPPING_ENTRY(ISD);
@@ -525,13 +523,13 @@ static void gt64120_writel (void *opaque, target_phys_addr_t addr,
/* not implemented */
break;
case GT_PCI0_CFGADDR:
- s->pci->config_reg = val & 0x80fffffc;
+ s->pci.config_reg = val & 0x80fffffc;
break;
case GT_PCI0_CFGDATA:
- if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci->config_reg & 0x00fff800))
+ if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci.config_reg & 0x00fff800))
val = bswap32(val);
- if (s->pci->config_reg & (1u << 31))
- pci_data_write(s->pci->bus, s->pci->config_reg, val, 4);
+ if (s->pci.config_reg & (1u << 31))
+ pci_data_write(s->pci.bus, s->pci.config_reg, val, 4);
break;
/* Interrupts */
@@ -765,14 +763,14 @@ static uint32_t gt64120_readl (void *opaque,
/* PCI Internal */
case GT_PCI0_CFGADDR:
- val = s->pci->config_reg;
+ val = s->pci.config_reg;
break;
case GT_PCI0_CFGDATA:
- if (!(s->pci->config_reg & (1 << 31)))
+ if (!(s->pci.config_reg & (1 << 31)))
val = 0xffffffff;
else
- val = pci_data_read(s->pci->bus, s->pci->config_reg, 4);
- if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci->config_reg & 0x00fff800))
+ val = pci_data_read(s->pci.bus, s->pci.config_reg, 4);
+ if (!(s->regs[GT_PCI0_CMD] & 1) && (s->pci.config_reg & 0x00fff800))
val = bswap32(val);
break;
@@ -864,7 +862,7 @@ static CPUReadMemoryFunc * const gt64120_read[] = {
>64120_readl,
};
-static int pci_gt64120_map_irq(PCIDevice *pci_dev, int irq_num)
+static int gt64120_pci_map_irq(PCIDevice *pci_dev, int irq_num)
{
int slot;
@@ -891,7 +889,7 @@ static int pci_gt64120_map_irq(PCIDevice *pci_dev, int irq_num)
static int pci_irq_levels[4];
-static void pci_gt64120_set_irq(void *opaque, int irq_num, int level)
+static void gt64120_pci_set_irq(void *opaque, int irq_num, int level)
{
int i, pic_irq, pic_level;
qemu_irq *pic = opaque;
@@ -1101,50 +1099,71 @@ static int gt64120_load(QEMUFile* f, void *opaque, int version_id)
return 0;
}
-PCIBus *pci_gt64120_init(qemu_irq *pic)
+PCIBus *gt64120_register(qemu_irq *pic)
+{
+ SysBusDevice *s;
+ GT64120State *d;
+ DeviceState *dev;
+
+ dev = qdev_create(NULL, "gt64120");
+ qdev_init_nofail(dev);
+ s = sysbus_from_qdev(dev);
+ d = FROM_SYSBUS(GT64120State, s);
+ d->pci.bus = pci_register_bus(&d->busdev.qdev, "pci",
+ gt64120_pci_set_irq, gt64120_pci_map_irq,
+ pic, PCI_DEVFN(18, 0), 4);
+ d->ISD_handle = cpu_register_io_memory(gt64120_read, gt64120_write, d,
+ DEVICE_NATIVE_ENDIAN);
+
+ pci_create_simple(d->pci.bus, PCI_DEVFN(0, 0), "gt64120_pci");
+ return d->pci.bus;
+}
+
+static int gt64120_init(SysBusDevice *dev)
{
GT64120State *s;
- PCIDevice *d;
- s = qemu_mallocz(sizeof(GT64120State));
- s->pci = qemu_mallocz(sizeof(GT64120PCIState));
+ s = FROM_SYSBUS(GT64120State, dev);
- s->pci->bus = pci_register_bus(NULL, "pci",
- pci_gt64120_set_irq, pci_gt64120_map_irq,
- pic, PCI_DEVFN(18, 0), 4);
- s->ISD_handle = cpu_register_io_memory(gt64120_read, gt64120_write, s,
- DEVICE_NATIVE_ENDIAN);
- d = pci_register_device(s->pci->bus, "GT64120 PCI Bus", sizeof(PCIDevice),
- 0, NULL, NULL);
+ qemu_register_reset(gt64120_reset, s);
+ register_savevm(&dev->qdev, "GT64120 PCI Bus", 0, 1,
+ gt64120_save, gt64120_load, &s->pci);
+ return 0;
+}
+static int gt64120_pci_init(PCIDevice *d)
+{
/* FIXME: Malta specific hw assumptions ahead */
-
pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_MARVELL);
pci_config_set_device_id(d->config, PCI_DEVICE_ID_MARVELL_GT6412X);
-
- d->config[0x04] = 0x00;
- d->config[0x05] = 0x00;
- d->config[0x06] = 0x80;
- d->config[0x07] = 0x02;
-
- d->config[0x08] = 0x10;
- d->config[0x09] = 0x00;
+ pci_set_word(d->config + PCI_COMMAND, 0);
+ pci_set_word(d->config + PCI_STATUS,
+ PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
+ pci_set_byte(d->config + PCI_CLASS_REVISION, 0x10);
+ pci_config_set_prog_interface(d->config, 0);
pci_config_set_class(d->config, PCI_CLASS_BRIDGE_HOST);
+ pci_set_long(d->config + PCI_BASE_ADDRESS_0, 0x00000008);
+ pci_set_long(d->config + PCI_BASE_ADDRESS_1, 0x01000008);
+ pci_set_long(d->config + PCI_BASE_ADDRESS_2, 0x1c000000);
+ pci_set_long(d->config + PCI_BASE_ADDRESS_3, 0x1f000000);
+ pci_set_long(d->config + PCI_BASE_ADDRESS_4, 0x14000000);
+ pci_set_long(d->config + PCI_BASE_ADDRESS_5, 0x14000001);
+ pci_set_byte(d->config + 0x3d, 0x01);
- d->config[0x10] = 0x08;
- d->config[0x14] = 0x08;
- d->config[0x17] = 0x01;
- d->config[0x1B] = 0x1c;
- d->config[0x1F] = 0x1f;
- d->config[0x23] = 0x14;
- d->config[0x24] = 0x01;
- d->config[0x27] = 0x14;
- d->config[0x3D] = 0x01;
-
- gt64120_reset(s);
+ return 0;
+}
- register_savevm(&d->qdev, "GT64120 PCI Bus", 0, 1,
- gt64120_save, gt64120_load, d);
+static PCIDeviceInfo gt64120_pci_info = {
+ .qdev.name = "gt64120_pci",
+ .qdev.size = sizeof(PCIDevice),
+ .init = gt64120_pci_init,
+};
- return s->pci->bus;
+static void gt64120_pci_register_devices(void)
+{
+ sysbus_register_dev("gt64120", sizeof(GT64120State),
+ gt64120_init);
+ pci_qdev_register(>64120_pci_info);
}
+
+device_init(gt64120_pci_register_devices)
diff --git a/hw/mips.h b/hw/mips.h
index 617ea10..757e8f9 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -3,7 +3,7 @@
/* Definitions for mips board emulation. */
/* gt64xxx.c */
-PCIBus *pci_gt64120_init(qemu_irq *pic);
+PCIBus *gt64120_register(qemu_irq *pic);
/* bonito.c */
PCIBus *bonito_init(qemu_irq *pic);
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index d3ba969..8755416 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -921,7 +921,7 @@ void mips_malta_init (ram_addr_t ram_size,
i8259 = i8259_init(env->irq[2]);
/* Northbridge */
- pci_bus = pci_gt64120_init(i8259);
+ pci_bus = gt64120_register(i8259);
/* Southbridge */
commit cf154394bd0a8e77c3cca3acefbad9b7a54efdaf
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Wed Jan 19 18:23:59 2011 +0100
sh_pci: qdev conversion
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/r2d.c b/hw/r2d.c
index 90d1af2..a0f8c1f 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -23,13 +23,13 @@
* THE SOFTWARE.
*/
+#include "sysbus.h"
#include "hw.h"
#include "sh.h"
#include "devices.h"
#include "sysemu.h"
#include "boards.h"
#include "pci.h"
-#include "sh_pci.h"
#include "net.h"
#include "sh7750_regs.h"
#include "ide.h"
@@ -195,19 +195,6 @@ static qemu_irq *r2d_fpga_init(target_phys_addr_t base, qemu_irq irl)
return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS);
}
-static void r2d_pci_set_irq(void *opaque, int n, int l)
-{
- qemu_irq *p = opaque;
-
- qemu_set_irq(p[n], l);
-}
-
-static int r2d_pci_map_irq(PCIDevice *d, int irq_num)
-{
- const int intx[] = { PCI_INTA, PCI_INTB, PCI_INTC, PCI_INTD };
- return intx[d->devfn >> 3];
-}
-
typedef struct ResetData {
CPUState *env;
uint32_t vector;
@@ -268,7 +255,8 @@ static void r2d_init(ram_addr_t ram_size,
/* Register peripherals */
s = sh7750_init(env);
irq = r2d_fpga_init(0x04000000, sh7750_irl(s));
- sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4);
+ sysbus_create_varargs("sh_pci", 0x1e200000, irq[PCI_INTA], irq[PCI_INTB],
+ irq[PCI_INTC], irq[PCI_INTD], NULL);
sm501_init(0x10000000, SM501_VRAM_SIZE, irq[SM501], serial_hds[2]);
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index 072078b..e99d8db 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -21,24 +21,26 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "hw.h"
+#include "sysbus.h"
#include "sh.h"
#include "pci.h"
#include "pci_host.h"
-#include "sh_pci.h"
#include "bswap.h"
-typedef struct {
+typedef struct SHPCIState {
+ SysBusDevice busdev;
PCIBus *bus;
PCIDevice *dev;
+ qemu_irq irq[4];
+ int memconfig;
uint32_t par;
uint32_t mbr;
uint32_t iobr;
-} SHPCIC;
+} SHPCIState;
static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val)
{
- SHPCIC *pcic = p;
+ SHPCIState *pcic = p;
switch(addr) {
case 0 ... 0xfc:
cpu_to_le32w((uint32_t*)(pcic->dev->config + addr), val);
@@ -65,7 +67,7 @@ static void sh_pci_reg_write (void *p, target_phys_addr_t addr, uint32_t val)
static uint32_t sh_pci_reg_read (void *p, target_phys_addr_t addr)
{
- SHPCIC *pcic = p;
+ SHPCIState *pcic = p;
switch(addr) {
case 0 ... 0xfc:
return le32_to_cpup((uint32_t*)(pcic->dev->config + addr));
@@ -91,32 +93,69 @@ static MemOp sh_pci_reg = {
{ NULL, NULL, sh_pci_reg_write },
};
-PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
- void *opaque, int devfn_min, int nirq)
+static int sh_pci_map_irq(PCIDevice *d, int irq_num)
+{
+ return (d->devfn >> 3);
+}
+
+static void sh_pci_set_irq(void *opaque, int irq_num, int level)
+{
+ qemu_irq *pic = opaque;
+
+ qemu_set_irq(pic[irq_num], level);
+}
+
+static void sh_pci_map(SysBusDevice *dev, target_phys_addr_t base)
+{
+ SHPCIState *s = FROM_SYSBUS(SHPCIState, dev);
+
+ cpu_register_physical_memory(P4ADDR(base), 0x224, s->memconfig);
+ cpu_register_physical_memory(A7ADDR(base), 0x224, s->memconfig);
+
+ s->iobr = 0xfe240000;
+ isa_mmio_init(s->iobr, 0x40000);
+}
+
+static int sh_pci_init_device(SysBusDevice *dev)
+{
+ SHPCIState *s;
+ int i;
+
+ s = FROM_SYSBUS(SHPCIState, dev);
+ for (i = 0; i < 4; i++) {
+ sysbus_init_irq(dev, &s->irq[i]);
+ }
+ s->bus = pci_register_bus(&s->busdev.qdev, "pci",
+ sh_pci_set_irq, sh_pci_map_irq,
+ s->irq, PCI_DEVFN(0, 0), 4);
+ s->memconfig = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w,
+ s, DEVICE_NATIVE_ENDIAN);
+ sysbus_init_mmio_cb(dev, 0x224, sh_pci_map);
+ s->dev = pci_create_simple(s->bus, PCI_DEVFN(0, 0), "sh_pci_host");
+ return 0;
+}
+
+static int sh_pci_host_init(PCIDevice *d)
+{
+ pci_config_set_vendor_id(d->config, PCI_VENDOR_ID_HITACHI);
+ pci_config_set_device_id(d->config, PCI_DEVICE_ID_HITACHI_SH7751R);
+ pci_set_word(d->config + PCI_COMMAND, PCI_COMMAND_WAIT);
+ pci_set_word(d->config + PCI_STATUS, PCI_STATUS_CAP_LIST |
+ PCI_STATUS_FAST_BACK | PCI_STATUS_DEVSEL_MEDIUM);
+ return 0;
+}
+
+static PCIDeviceInfo sh_pci_host_info = {
+ .qdev.name = "sh_pci_host",
+ .qdev.size = sizeof(PCIDevice),
+ .init = sh_pci_host_init,
+};
+
+static void sh_pci_register_devices(void)
{
- SHPCIC *p;
- int reg;
-
- p = qemu_mallocz(sizeof(SHPCIC));
- p->bus = pci_register_bus(NULL, "pci",
- set_irq, map_irq, opaque, devfn_min, nirq);
-
- p->dev = pci_register_device(p->bus, "SH PCIC", sizeof(PCIDevice),
- -1, NULL, NULL);
- reg = cpu_register_io_memory(sh_pci_reg.r, sh_pci_reg.w, p,
- DEVICE_NATIVE_ENDIAN);
- cpu_register_physical_memory(0x1e200000, 0x224, reg);
- cpu_register_physical_memory(0xfe200000, 0x224, reg);
-
- p->iobr = 0xfe240000;
- isa_mmio_init(p->iobr, 0x40000);
-
- pci_config_set_vendor_id(p->dev->config, PCI_VENDOR_ID_HITACHI);
- pci_config_set_device_id(p->dev->config, PCI_DEVICE_ID_HITACHI_SH7751R);
- p->dev->config[0x04] = 0x80;
- p->dev->config[0x05] = 0x00;
- p->dev->config[0x06] = 0x90;
- p->dev->config[0x07] = 0x02;
-
- return p->bus;
+ sysbus_register_dev("sh_pci", sizeof(SHPCIState),
+ sh_pci_init_device);
+ pci_qdev_register(&sh_pci_host_info);
}
+
+device_init(sh_pci_register_devices)
diff --git a/hw/sh_pci.h b/hw/sh_pci.h
deleted file mode 100644
index b1a5ec3..0000000
--- a/hw/sh_pci.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef QEMU_SH_PCI_H
-#define QEMU_SH_PCI_H
-
-#include "qemu-common.h"
-
-PCIBus *sh_pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
- void *pic, int devfn_min, int nirq);
-
-#endif
commit b7d2b020934d0d3ae857ff486919601819e96dce
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Wed Jan 19 11:38:36 2011 +0100
sh_serial: process all received characters
When operating on the SCIF, process all the received characters, as long
as the FIFO can handle them.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index ae9a207..191f4a6 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -293,26 +293,6 @@ static int sh_serial_can_receive(sh_serial_state *s)
return s->scr & (1 << 4);
}
-static void sh_serial_receive_byte(sh_serial_state *s, int ch)
-{
- if (s->feat & SH_SERIAL_FEAT_SCIF) {
- if (s->rx_cnt < SH_RX_FIFO_LENGTH) {
- s->rx_fifo[s->rx_head++] = ch;
- if (s->rx_head == SH_RX_FIFO_LENGTH)
- s->rx_head = 0;
- s->rx_cnt++;
- if (s->rx_cnt >= s->rtrg) {
- s->flags |= SH_SERIAL_FLAG_RDF;
- if (s->scr & (1 << 6) && s->rxi) {
- qemu_set_irq(s->rxi, 1);
- }
- }
- }
- } else {
- s->rx_fifo[0] = ch;
- }
-}
-
static void sh_serial_receive_break(sh_serial_state *s)
{
if (s->feat & SH_SERIAL_FEAT_SCIF)
@@ -328,7 +308,27 @@ static int sh_serial_can_receive1(void *opaque)
static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
{
sh_serial_state *s = opaque;
- sh_serial_receive_byte(s, buf[0]);
+
+ if (s->feat & SH_SERIAL_FEAT_SCIF) {
+ int i;
+ for (i = 0; i < size; i++) {
+ if (s->rx_cnt < SH_RX_FIFO_LENGTH) {
+ s->rx_fifo[s->rx_head++] = buf[i];
+ if (s->rx_head == SH_RX_FIFO_LENGTH) {
+ s->rx_head = 0;
+ }
+ s->rx_cnt++;
+ if (s->rx_cnt >= s->rtrg) {
+ s->flags |= SH_SERIAL_FLAG_RDF;
+ if (s->scr & (1 << 6) && s->rxi) {
+ qemu_set_irq(s->rxi, 1);
+ }
+ }
+ }
+ }
+ } else {
+ s->rx_fifo[0] = buf[0];
+ }
}
static void sh_serial_event(void *opaque, int event)
commit b7277ac28908dbd9e95c3ce084da3d4e6539d0c8
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Wed Jan 19 11:35:02 2011 +0100
sh_serial: remove one level of indirection
The indirection functions are empty since commit
8da3ff180974732fc4272cb4433fef85c1822961.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/sh_serial.c b/hw/sh_serial.c
index 1bdc0a5..ae9a207 100644
--- a/hw/sh_serial.c
+++ b/hw/sh_serial.c
@@ -74,7 +74,7 @@ static void sh_serial_clear_fifo(sh_serial_state * s)
s->rx_tail = 0;
}
-static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
+static void sh_serial_write(void *opaque, uint32_t offs, uint32_t val)
{
sh_serial_state *s = opaque;
unsigned char ch;
@@ -185,7 +185,7 @@ static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
abort();
}
-static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs)
+static uint32_t sh_serial_read(void *opaque, uint32_t offs)
{
sh_serial_state *s = opaque;
uint32_t ret = ~0;
@@ -338,19 +338,6 @@ static void sh_serial_event(void *opaque, int event)
sh_serial_receive_break(s);
}
-static uint32_t sh_serial_read (void *opaque, target_phys_addr_t addr)
-{
- sh_serial_state *s = opaque;
- return sh_serial_ioport_read(s, addr);
-}
-
-static void sh_serial_write (void *opaque,
- target_phys_addr_t addr, uint32_t value)
-{
- sh_serial_state *s = opaque;
- sh_serial_ioport_write(s, addr, value);
-}
-
static CPUReadMemoryFunc * const sh_serial_readfn[] = {
&sh_serial_read,
&sh_serial_read,
commit 373dfc441d55fe6619929fd049ab635bdfca9e62
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Mon Jan 17 19:29:34 2011 +0100
usb-hid: modifiers should generate an event
When a modifier key is pressed or released, the USB HID keyboard still
answers NAK, unless another key is also pressed or released.
The patch fixes that by calling usb_hid_changed() when a modifier key
is pressed or released.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index e8de301..12bf46f 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -460,15 +460,18 @@ static void usb_keyboard_event(void *opaque, int keycode)
case 0xe0:
if (s->modifiers & (1 << 9)) {
s->modifiers ^= 3 << 8;
+ usb_hid_changed(hs);
return;
}
case 0xe1 ... 0xe7:
if (keycode & (1 << 7)) {
s->modifiers &= ~(1 << (hid_code & 0x0f));
+ usb_hid_changed(hs);
return;
}
case 0xe8 ... 0xef:
s->modifiers |= 1 << (hid_code & 0x0f);
+ usb_hid_changed(hs);
return;
}
commit de4af5f7928bb68d4e2b576598c245a256fcabbb
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Mon Jan 17 19:29:33 2011 +0100
softfloat: fix floatx80_is_{quiet,signaling}_nan()
floatx80_is_{quiet,signaling}_nan() functions are incorrectly detecting
the type of NaN, depending on SNAN_BIT_IS_ONE, one of the two is
returning the correct value, and the other true for any kind of NaN.
This patch fixes that by applying the same kind of comparison as for
other float formats, but taking into account the explicit bit.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 11521ce..eb644b2 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -468,7 +468,8 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is a
-| quiet NaN; otherwise returns 0.
+| quiet NaN; otherwise returns 0. This slightly differs from the same
+| function for other types as floatx80 has an explicit bit.
*----------------------------------------------------------------------------*/
int floatx80_is_quiet_nan( floatx80 a )
@@ -482,19 +483,22 @@ int floatx80_is_quiet_nan( floatx80 a )
&& (bits64) ( aLow<<1 )
&& ( a.low == aLow );
#else
- return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
+ return ( ( a.high & 0x7FFF ) == 0x7FFF )
+ && (LIT64( 0x8000000000000000 ) <= ((bits64) ( a.low<<1 )));
#endif
}
/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is a
-| signaling NaN; otherwise returns 0.
+| signaling NaN; otherwise returns 0. This slightly differs from the same
+| function for other types as floatx80 has an explicit bit.
*----------------------------------------------------------------------------*/
int floatx80_is_signaling_nan( floatx80 a )
{
#if SNAN_BIT_IS_ONE
- return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
+ return ( ( a.high & 0x7FFF ) == 0x7FFF )
+ && (LIT64( 0x8000000000000000 ) <= ((bits64) ( a.low<<1 )));
#else
bits64 aLow;
commit 3a34dfd7f600e235687fece76b8f763362b883b2
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Thu Jan 20 12:16:57 2011 +0100
tcg: README, name deposit second argument len/LEN
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/tcg/README b/tcg/README
index a50ecc6..6600122 100644
--- a/tcg/README
+++ b/tcg/README
@@ -285,10 +285,10 @@ the four high order bytes are set to zero.
Indicate that the value of t0 won't be used later. It is useful to
force dead code elimination.
-* deposit_i32/i64 dest, t1, t2, pos, loc
+* deposit_i32/i64 dest, t1, t2, pos, len
Deposit T2 as a bitfield into T1, placing the result in DEST.
-The bitfield is described by POS/LOC, which are immediate values:
+The bitfield is described by POS/LEN, which are immediate values:
LEN - the length of the bitfield
POS - the position of the first bit, counting from the LSB
commit c832e3de64f1069313fc0672087791cc3dd5b4d8
Author: Richard Henderson <rth at twiddle.net>
Date: Mon Jan 10 19:23:47 2011 -0800
target-i386: Use deposit operation.
Use this for assignment to the low byte or low word of a register.
Acked-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 7b6e3c2..c008450 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -274,28 +274,16 @@ static inline void gen_op_andl_A0_ffff(void)
static inline void gen_op_mov_reg_v(int ot, int reg, TCGv t0)
{
- TCGv tmp;
-
switch(ot) {
case OT_BYTE:
- tmp = tcg_temp_new();
- tcg_gen_ext8u_tl(tmp, t0);
if (reg < 4 X86_64_DEF( || reg >= 8 || x86_64_hregs)) {
- tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xff);
- tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp);
+ tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 8);
} else {
- tcg_gen_shli_tl(tmp, tmp, 8);
- tcg_gen_andi_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], ~0xff00);
- tcg_gen_or_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], tmp);
+ tcg_gen_deposit_tl(cpu_regs[reg - 4], cpu_regs[reg - 4], t0, 8, 8);
}
- tcg_temp_free(tmp);
break;
case OT_WORD:
- tmp = tcg_temp_new();
- tcg_gen_ext16u_tl(tmp, t0);
- tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
- tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp);
- tcg_temp_free(tmp);
+ tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], t0, 0, 16);
break;
default: /* XXX this shouldn't be reached; abort? */
case OT_LONG:
@@ -323,15 +311,9 @@ static inline void gen_op_mov_reg_T1(int ot, int reg)
static inline void gen_op_mov_reg_A0(int size, int reg)
{
- TCGv tmp;
-
switch(size) {
case 0:
- tmp = tcg_temp_new();
- tcg_gen_ext16u_tl(tmp, cpu_A0);
- tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
- tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], tmp);
- tcg_temp_free(tmp);
+ tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_A0, 0, 16);
break;
default: /* XXX this shouldn't be reached; abort? */
case 1:
@@ -415,9 +397,7 @@ static inline void gen_op_add_reg_im(int size, int reg, int32_t val)
switch(size) {
case 0:
tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
- tcg_gen_ext16u_tl(cpu_tmp0, cpu_tmp0);
- tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
- tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0);
+ tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
break;
case 1:
tcg_gen_addi_tl(cpu_tmp0, cpu_regs[reg], val);
@@ -439,9 +419,7 @@ static inline void gen_op_add_reg_T0(int size, int reg)
switch(size) {
case 0:
tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
- tcg_gen_ext16u_tl(cpu_tmp0, cpu_tmp0);
- tcg_gen_andi_tl(cpu_regs[reg], cpu_regs[reg], ~0xffff);
- tcg_gen_or_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0);
+ tcg_gen_deposit_tl(cpu_regs[reg], cpu_regs[reg], cpu_tmp0, 0, 16);
break;
case 1:
tcg_gen_add_tl(cpu_tmp0, cpu_regs[reg], cpu_T[0]);
commit b7767f0f3cb6879b42ed47e9375313829028adaf
Author: Richard Henderson <rth at twiddle.net>
Date: Mon Jan 10 19:23:42 2011 -0800
tcg: Define "deposit" as an optional operation.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/tcg/README b/tcg/README
index a18a87f..a50ecc6 100644
--- a/tcg/README
+++ b/tcg/README
@@ -285,6 +285,20 @@ the four high order bytes are set to zero.
Indicate that the value of t0 won't be used later. It is useful to
force dead code elimination.
+* deposit_i32/i64 dest, t1, t2, pos, loc
+
+Deposit T2 as a bitfield into T1, placing the result in DEST.
+The bitfield is described by POS/LOC, which are immediate values:
+
+ LEN - the length of the bitfield
+ POS - the position of the first bit, counting from the LSB
+
+For example, pos=8, len=4 indicates a 4-bit field at bit 8.
+This operation would be equivalent to
+
+ dest = (t1 & ~0x0f00) | ((t2 << 8) & 0x0f00)
+
+
********* Conditional moves
* setcond_i32/i64 cond, dest, t1, t2
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 3ee0a58..207a89f 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -254,6 +254,30 @@ static inline void tcg_gen_op5i_i64(TCGOpcode opc, TCGv_i64 arg1, TCGv_i64 arg2,
*gen_opparam_ptr++ = arg5;
}
+static inline void tcg_gen_op5ii_i32(TCGOpcode opc, TCGv_i32 arg1,
+ TCGv_i32 arg2, TCGv_i32 arg3,
+ TCGArg arg4, TCGArg arg5)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I32(arg3);
+ *gen_opparam_ptr++ = arg4;
+ *gen_opparam_ptr++ = arg5;
+}
+
+static inline void tcg_gen_op5ii_i64(TCGOpcode opc, TCGv_i64 arg1,
+ TCGv_i64 arg2, TCGv_i64 arg3,
+ TCGArg arg4, TCGArg arg5)
+{
+ *gen_opc_ptr++ = opc;
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg1);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg2);
+ *gen_opparam_ptr++ = GET_TCGV_I64(arg3);
+ *gen_opparam_ptr++ = arg4;
+ *gen_opparam_ptr++ = arg5;
+}
+
static inline void tcg_gen_op6_i32(TCGOpcode opc, TCGv_i32 arg1, TCGv_i32 arg2,
TCGv_i32 arg3, TCGv_i32 arg4, TCGv_i32 arg5,
TCGv_i32 arg6)
@@ -2071,6 +2095,44 @@ static inline void tcg_gen_rotri_i64(TCGv_i64 ret, TCGv_i64 arg1, int64_t arg2)
}
}
+static inline void tcg_gen_deposit_i32(TCGv_i32 ret, TCGv_i32 arg1,
+ TCGv_i32 arg2, unsigned int ofs,
+ unsigned int len)
+{
+#ifdef TCG_TARGET_HAS_deposit_i32
+ tcg_gen_op5ii_i32(INDEX_op_deposit_i32, ret, arg1, arg2, ofs, len);
+#else
+ uint32_t mask = (1u << len) - 1;
+ TCGv_i32 t1 = tcg_temp_new_i32 ();
+
+ tcg_gen_andi_i32(t1, arg2, mask);
+ tcg_gen_shli_i32(t1, t1, ofs);
+ tcg_gen_andi_i32(ret, arg1, ~(mask << ofs));
+ tcg_gen_or_i32(ret, ret, t1);
+
+ tcg_temp_free_i32(t1);
+#endif
+}
+
+static inline void tcg_gen_deposit_i64(TCGv_i64 ret, TCGv_i64 arg1,
+ TCGv_i64 arg2, unsigned int ofs,
+ unsigned int len)
+{
+#ifdef TCG_TARGET_HAS_deposit_i64
+ tcg_gen_op5ii_i64(INDEX_op_deposit_i64, ret, arg1, arg2, ofs, len);
+#else
+ uint64_t mask = (1ull << len) - 1;
+ TCGv_i64 t1 = tcg_temp_new_i64 ();
+
+ tcg_gen_andi_i64(t1, arg2, mask);
+ tcg_gen_shli_i64(t1, t1, ofs);
+ tcg_gen_andi_i64(ret, arg1, ~(mask << ofs));
+ tcg_gen_or_i64(ret, ret, t1);
+
+ tcg_temp_free_i64(t1);
+#endif
+}
+
/***************************************/
/* QEMU specific operations. Their type depend on the QEMU CPU
type. */
@@ -2384,6 +2446,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
#define tcg_gen_rotli_tl tcg_gen_rotli_i64
#define tcg_gen_rotr_tl tcg_gen_rotr_i64
#define tcg_gen_rotri_tl tcg_gen_rotri_i64
+#define tcg_gen_deposit_tl tcg_gen_deposit_i64
#define tcg_const_tl tcg_const_i64
#define tcg_const_local_tl tcg_const_local_i64
#else
@@ -2454,6 +2517,7 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index)
#define tcg_gen_rotli_tl tcg_gen_rotli_i32
#define tcg_gen_rotr_tl tcg_gen_rotr_i32
#define tcg_gen_rotri_tl tcg_gen_rotri_i32
+#define tcg_gen_deposit_tl tcg_gen_deposit_i32
#define tcg_const_tl tcg_const_i32
#define tcg_const_local_tl tcg_const_local_i32
#endif
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 2a98fed..2c7ca1a 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -78,6 +78,9 @@ DEF(sar_i32, 1, 2, 0, 0)
DEF(rotl_i32, 1, 2, 0, 0)
DEF(rotr_i32, 1, 2, 0, 0)
#endif
+#ifdef TCG_TARGET_HAS_deposit_i32
+DEF(deposit_i32, 1, 2, 2, 0)
+#endif
DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
#if TCG_TARGET_REG_BITS == 32
@@ -168,6 +171,9 @@ DEF(sar_i64, 1, 2, 0, 0)
DEF(rotl_i64, 1, 2, 0, 0)
DEF(rotr_i64, 1, 2, 0, 0)
#endif
+#ifdef TCG_TARGET_HAS_deposit_i64
+DEF(deposit_i64, 1, 2, 2, 0)
+#endif
DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
#ifdef TCG_TARGET_HAS_ext8s_i64
commit 9f8beb6636fdd913a25fa536238a3a047ce4cf63
Author: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
Date: Wed Jan 19 23:18:00 2011 +0100
microblaze: Add support for load/store reversed
Load/store reversed (lwr/swr) are insns that endian translate
the sub-word part of the address and byteswap the data lanes.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 2673167..4b6ae06 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -817,12 +817,35 @@ static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
return t;
}
+static inline void dec_byteswap(DisasContext *dc, TCGv dst, TCGv src, int size)
+{
+ if (size == 4) {
+ tcg_gen_bswap32_tl(dst, src);
+ } else if (size == 2) {
+ TCGv t = tcg_temp_new();
+
+ /* bswap16 assumes the high bits are zero. */
+ tcg_gen_andi_tl(t, src, 0xffff);
+ tcg_gen_bswap16_tl(dst, t);
+ tcg_temp_free(t);
+ } else {
+ /* Ignore.
+ cpu_abort(dc->env, "Invalid ldst byteswap size %d\n", size);
+ */
+ }
+}
+
static void dec_load(DisasContext *dc)
{
TCGv t, *addr;
- unsigned int size;
+ unsigned int size, rev = 0;
size = 1 << (dc->opcode & 3);
+
+ if (!dc->type_b) {
+ rev = (dc->ir >> 9) & 1;
+ }
+
if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
&& (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
tcg_gen_movi_tl(cpu_SR[SR_ESR], ESR_EC_ILLEGAL_OP);
@@ -830,10 +853,63 @@ static void dec_load(DisasContext *dc)
return;
}
- LOG_DIS("l %x %d\n", dc->opcode, size);
+ LOG_DIS("l%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "");
+
t_sync_flags(dc);
addr = compute_ldst_addr(dc, &t);
+ /*
+ * When doing reverse accesses we need to do two things.
+ *
+ * 1. Reverse the address wrt endianess.
+ * 2. Byteswap the data lanes on the way back into the CPU core.
+ */
+ if (rev && size != 4) {
+ /* Endian reverse the address. t is addr. */
+ switch (size) {
+ case 1:
+ {
+ /* 00 -> 11
+ 01 -> 10
+ 10 -> 10
+ 11 -> 00 */
+ TCGv low = tcg_temp_new();
+
+ /* Force addr into the temp. */
+ if (addr != &t) {
+ t = tcg_temp_new();
+ tcg_gen_mov_tl(t, *addr);
+ addr = &t;
+ }
+
+ tcg_gen_andi_tl(low, t, 3);
+ tcg_gen_sub_tl(low, tcg_const_tl(3), low);
+ tcg_gen_andi_tl(t, t, ~3);
+ tcg_gen_or_tl(t, t, low);
+ tcg_gen_mov_tl(env_debug, low);
+ tcg_gen_mov_tl(env_imm, t);
+ tcg_temp_free(low);
+ break;
+ }
+
+ case 2:
+ /* 00 -> 10
+ 10 -> 00. */
+ /* Force addr into the temp. */
+ if (addr != &t) {
+ t = tcg_temp_new();
+ tcg_gen_xori_tl(t, *addr, 2);
+ addr = &t;
+ } else {
+ tcg_gen_xori_tl(t, t, 2);
+ }
+ break;
+ default:
+ cpu_abort(dc->env, "Invalid reverse size\n");
+ break;
+ }
+ }
+
/* If we get a fault on a dslot, the jmpstate better be in sync. */
sync_jmpstate(dc);
@@ -852,13 +928,22 @@ static void dec_load(DisasContext *dc)
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
tcg_const_tl(0), tcg_const_tl(size - 1));
- if (dc->rd)
- tcg_gen_mov_tl(cpu_R[dc->rd], v);
+ if (dc->rd) {
+ if (rev) {
+ dec_byteswap(dc, cpu_R[dc->rd], v, size);
+ } else {
+ tcg_gen_mov_tl(cpu_R[dc->rd], v);
+ }
+ }
tcg_temp_free(v);
} else {
if (dc->rd) {
gen_load(dc, cpu_R[dc->rd], *addr, size);
+ if (rev) {
+ dec_byteswap(dc, cpu_R[dc->rd], cpu_R[dc->rd], size);
+ }
} else {
+ /* We are loading into r0, no need to reverse. */
gen_load(dc, env_imm, *addr, size);
}
}
@@ -885,9 +970,12 @@ static void gen_store(DisasContext *dc, TCGv addr, TCGv val,
static void dec_store(DisasContext *dc)
{
TCGv t, *addr;
- unsigned int size;
+ unsigned int size, rev = 0;
size = 1 << (dc->opcode & 3);
+ if (!dc->type_b) {
+ rev = (dc->ir >> 9) & 1;
+ }
if (size > 4 && (dc->tb_flags & MSR_EE_FLAG)
&& (dc->env->pvr.regs[2] & PVR2_ILL_OPCODE_EXC_MASK)) {
@@ -896,19 +984,84 @@ static void dec_store(DisasContext *dc)
return;
}
- LOG_DIS("s%d%s\n", size, dc->type_b ? "i" : "");
+ LOG_DIS("s%d%s%s\n", size, dc->type_b ? "i" : "", rev ? "r" : "");
t_sync_flags(dc);
/* If we get a fault on a dslot, the jmpstate better be in sync. */
sync_jmpstate(dc);
addr = compute_ldst_addr(dc, &t);
- gen_store(dc, *addr, cpu_R[dc->rd], size);
+ if (rev && size != 4) {
+ /* Endian reverse the address. t is addr. */
+ switch (size) {
+ case 1:
+ {
+ /* 00 -> 11
+ 01 -> 10
+ 10 -> 10
+ 11 -> 00 */
+ TCGv low = tcg_temp_new();
+
+ /* Force addr into the temp. */
+ if (addr != &t) {
+ t = tcg_temp_new();
+ tcg_gen_mov_tl(t, *addr);
+ addr = &t;
+ }
+
+ tcg_gen_andi_tl(low, t, 3);
+ tcg_gen_sub_tl(low, tcg_const_tl(3), low);
+ tcg_gen_andi_tl(t, t, ~3);
+ tcg_gen_or_tl(t, t, low);
+ tcg_gen_mov_tl(env_debug, low);
+ tcg_gen_mov_tl(env_imm, t);
+ tcg_temp_free(low);
+ break;
+ }
+
+ case 2:
+ /* 00 -> 10
+ 10 -> 00. */
+ /* Force addr into the temp. */
+ if (addr != &t) {
+ t = tcg_temp_new();
+ tcg_gen_xori_tl(t, *addr, 2);
+ addr = &t;
+ } else {
+ tcg_gen_xori_tl(t, t, 2);
+ }
+ break;
+ default:
+ cpu_abort(dc->env, "Invalid reverse size\n");
+ break;
+ }
+
+ if (size != 1) {
+ TCGv bs_data = tcg_temp_new();
+ dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
+ gen_store(dc, *addr, bs_data, size);
+ tcg_temp_free(bs_data);
+ } else {
+ gen_store(dc, *addr, cpu_R[dc->rd], size);
+ }
+ } else {
+ if (rev) {
+ TCGv bs_data = tcg_temp_new();
+ dec_byteswap(dc, bs_data, cpu_R[dc->rd], size);
+ gen_store(dc, *addr, bs_data, size);
+ tcg_temp_free(bs_data);
+ } else {
+ gen_store(dc, *addr, cpu_R[dc->rd], size);
+ }
+ }
/* Verify alignment if needed. */
if ((dc->env->pvr.regs[2] & PVR2_UNALIGNED_EXC_MASK) && size > 1) {
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
/* FIXME: if the alignment is wrong, we should restore the value
- * in memory.
+ * in memory. One possible way to acheive this is to probe
+ * the MMU prior to the memaccess, thay way we could put
+ * the alignment checks in between the probe and the mem
+ * access.
*/
gen_helper_memalign(*addr, tcg_const_tl(dc->rd),
tcg_const_tl(1), tcg_const_tl(size - 1));
commit 9ef55357634d57331243c780439efc596c8d460d
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Wed Jan 19 22:48:07 2011 +0100
microblaze: Tweak comment, fast cases -> common cases
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 2e236fb..2673167 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -788,7 +788,7 @@ static inline TCGv *compute_ldst_addr(DisasContext *dc, TCGv *t)
{
unsigned int extimm = dc->tb_flags & IMM_FLAG;
- /* Treat the fast cases first. */
+ /* Treat the common cases first. */
if (!dc->type_b) {
/* If any of the regs is r0, return a ptr to the other. */
if (dc->ra == 0) {
commit 2991181aaa026d8b1444bfaa9c4bcd82065ba5a3
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Wed Jan 19 21:18:19 2011 +0200
pci: fix device paths
Patch a6a7005d14b3c32d4864a718fb1cb19c789f58a5 generated
broken device paths. We snprintf with a length shorter
than the output, so the last character is discarded and replaced
by the null byte. Fix it up by snprintf to a buffer
which is larger by 1 byte and then memcpy the data (without
the null byte) to where we need it.
Reported-by: Christoph Hellwig <hch at lst.de>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/pci.c b/hw/pci.c
index 8d0e3df..c77f6e9 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -2032,10 +2032,13 @@ static char *pcibus_get_dev_path(DeviceState *dev)
* domain:Bus:Slot.Func for systems without nested PCI bridges.
* Slot.Function list specifies the slot and function numbers for all
* devices on the path from root to the specific device. */
- int domain_len = strlen("DDDD:00");
- int slot_len = strlen(":SS.F");
+ char domain[] = "DDDD:00";
+ char slot[] = ":SS.F";
+ int domain_len = sizeof domain - 1 /* For '\0' */;
+ int slot_len = sizeof slot - 1 /* For '\0' */;
int path_len;
char *path, *p;
+ int s;
/* Calculate # of slots on path between device and root. */;
slot_depth = 0;
@@ -2050,14 +2053,19 @@ static char *pcibus_get_dev_path(DeviceState *dev)
path[path_len] = '\0';
/* First field is the domain. */
- snprintf(path, domain_len, "%04x:00", pci_find_domain(d->bus));
+ s = snprintf(domain, sizeof domain, "%04x:00", pci_find_domain(d->bus));
+ assert(s == domain_len);
+ memcpy(path, domain, domain_len);
/* Fill in slot numbers. We walk up from device to root, so need to print
* them in the reverse order, last to first. */
p = path + path_len;
for (t = d; t; t = t->bus->parent_dev) {
p -= slot_len;
- snprintf(p, slot_len, ":%02x.%x", PCI_SLOT(t->devfn), PCI_FUNC(d->devfn));
+ s = snprintf(slot, sizeof slot, ":%02x.%x",
+ PCI_SLOT(t->devfn), PCI_FUNC(d->devfn));
+ assert(s == slot_len);
+ memcpy(p, slot, slot_len);
}
return path;
commit 1b5f56b134dc2d338911242424795de70c7475fd
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Tue Jan 18 21:34:51 2011 +0000
sparc: fix NaN handling
Fix several bugs in NaN handling:
* e in fcmpe* only changes qNaN handling
* FCC is unchanged if an exception is raised
* clear previous FTT before setting it
Reported-by: Mateusz Loskot <mateusz at loskot.net>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 58f9f82..b70970a 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -857,65 +857,77 @@ void helper_fsqrtq(void)
QT0 = float128_sqrt(QT1, &env->fp_status);
}
-#define GEN_FCMP(name, size, reg1, reg2, FS, TRAP) \
+#define GEN_FCMP(name, size, reg1, reg2, FS, E) \
void glue(helper_, name) (void) \
{ \
- target_ulong new_fsr; \
- \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr &= FSR_FTT_NMASK; \
+ if (E && (glue(size, _is_any_nan)(reg1) || \
+ glue(size, _is_any_nan)(reg2)) && \
+ (env->fsr & FSR_NVM)) { \
+ env->fsr |= FSR_NVC; \
+ env->fsr |= FSR_FTT_IEEE_EXCP; \
+ raise_exception(TT_FP_EXCP); \
+ } \
switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) { \
case float_relation_unordered: \
- new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
- if ((env->fsr & FSR_NVM) || TRAP) { \
- env->fsr |= new_fsr; \
+ if ((env->fsr & FSR_NVM)) { \
env->fsr |= FSR_NVC; \
env->fsr |= FSR_FTT_IEEE_EXCP; \
raise_exception(TT_FP_EXCP); \
} else { \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
env->fsr |= FSR_NVA; \
} \
break; \
case float_relation_less: \
- new_fsr = FSR_FCC0 << FS; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC0 << FS; \
break; \
case float_relation_greater: \
- new_fsr = FSR_FCC1 << FS; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC1 << FS; \
break; \
default: \
- new_fsr = 0; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
break; \
} \
- env->fsr |= new_fsr; \
}
-#define GEN_FCMPS(name, size, FS, TRAP) \
+#define GEN_FCMPS(name, size, FS, E) \
void glue(helper_, name)(float32 src1, float32 src2) \
{ \
- target_ulong new_fsr; \
- \
- env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr &= FSR_FTT_NMASK; \
+ if (E && (glue(size, _is_any_nan)(src1) || \
+ glue(size, _is_any_nan)(src2)) && \
+ (env->fsr & FSR_NVM)) { \
+ env->fsr |= FSR_NVC; \
+ env->fsr |= FSR_FTT_IEEE_EXCP; \
+ raise_exception(TT_FP_EXCP); \
+ } \
switch (glue(size, _compare) (src1, src2, &env->fp_status)) { \
case float_relation_unordered: \
- new_fsr = (FSR_FCC1 | FSR_FCC0) << FS; \
- if ((env->fsr & FSR_NVM) || TRAP) { \
- env->fsr |= new_fsr; \
+ if ((env->fsr & FSR_NVM)) { \
env->fsr |= FSR_NVC; \
env->fsr |= FSR_FTT_IEEE_EXCP; \
raise_exception(TT_FP_EXCP); \
} else { \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= (FSR_FCC1 | FSR_FCC0) << FS; \
env->fsr |= FSR_NVA; \
} \
break; \
case float_relation_less: \
- new_fsr = FSR_FCC0 << FS; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC0 << FS; \
break; \
case float_relation_greater: \
- new_fsr = FSR_FCC1 << FS; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
+ env->fsr |= FSR_FCC1 << FS; \
break; \
default: \
- new_fsr = 0; \
+ env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS); \
break; \
} \
- env->fsr |= new_fsr; \
}
GEN_FCMPS(fcmps, float32, 0, 0);
commit 5642463aeeb187597e217706d9ed2663cd3734c0
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Tue Jan 18 13:08:40 2011 +0000
target-arm: Log instruction start in TCG code
Add support for logging the start of instructions in TCG
code debug dumps for ARM targets.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 907d73a..c60cd18 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9199,6 +9199,10 @@ static inline void gen_intermediate_code_internal(CPUState *env,
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
+ if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
+ tcg_gen_debug_insn_start(dc->pc);
+ }
+
if (dc->thumb) {
disas_thumb_insn(env, dc);
if (dc->condexec_mask) {
commit 55807224561b9ac278bb65960b6c12666fd30db9
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Mon Jan 17 23:00:08 2011 +0100
mips: Break TBs after mfc0_count
Break the TB after reading the count register. This makes it
possible to take timer interrupts immediately after a read of
a possibly expired timer.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/target-mips/translate.c b/target-mips/translate.c
index cce77be..187930e 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -3410,8 +3410,10 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int s
gen_helper_mfc0_count(arg);
if (use_icount) {
gen_io_end();
- ctx->bstate = BS_STOP;
}
+ /* Break the TB to be able to take timer interrupts immediately
+ after reading count. */
+ ctx->bstate = BS_STOP;
rn = "Count";
break;
/* 6,7 are implementation dependent */
@@ -4581,8 +4583,10 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int
gen_helper_mfc0_count(arg);
if (use_icount) {
gen_io_end();
- ctx->bstate = BS_STOP;
}
+ /* Break the TB to be able to take timer interrupts immediately
+ after reading count. */
+ ctx->bstate = BS_STOP;
rn = "Count";
break;
/* 6,7 are implementation dependent */
commit e027e1f075afe36698ce55d86f01b7817707c8b6
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Tue Jan 18 00:12:22 2011 +0100
mips: Expire late timers when reading cp0_count
When reading cp0_count from a timer with a late trigger that should
already have expired, expire it and raise the timer irq.
This makes it possible for guest code (e.g, Linux) that first read
cp0_count, then compare it with cp0_compare and check for raised
timer interrupt lines to run reliably.
Acked-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/hw/mips_timer.c b/hw/mips_timer.c
index 8c32087..9c95f28 100644
--- a/hw/mips_timer.c
+++ b/hw/mips_timer.c
@@ -69,9 +69,17 @@ uint32_t cpu_mips_get_count (CPUState *env)
if (env->CP0_Cause & (1 << CP0Ca_DC)) {
return env->CP0_Count;
} else {
+ uint64_t now;
+
+ now = qemu_get_clock(vm_clock);
+ if (qemu_timer_pending(env->timer)
+ && qemu_timer_expired(env->timer, now)) {
+ /* The timer has already expired. */
+ cpu_mips_timer_expire(env);
+ }
+
return env->CP0_Count +
- (uint32_t)muldiv64(qemu_get_clock(vm_clock),
- TIMER_FREQ, get_ticks_per_sec());
+ (uint32_t)muldiv64(now, TIMER_FREQ, get_ticks_per_sec());
}
}
commit b1dfe6437c776f6441cf8b71c706f32f2456c530
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Tue Jan 18 00:07:49 2011 +0100
mips: Break out cpu_mips_timer_expire
Reorganize for future patches, no functional change.
Acked-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/hw/mips_timer.c b/hw/mips_timer.c
index e3beee8..8c32087 100644
--- a/hw/mips_timer.c
+++ b/hw/mips_timer.c
@@ -42,16 +42,6 @@ uint32_t cpu_mips_get_random (CPUState *env)
}
/* MIPS R4K timer */
-uint32_t cpu_mips_get_count (CPUState *env)
-{
- if (env->CP0_Cause & (1 << CP0Ca_DC))
- return env->CP0_Count;
- else
- return env->CP0_Count +
- (uint32_t)muldiv64(qemu_get_clock(vm_clock),
- TIMER_FREQ, get_ticks_per_sec());
-}
-
static void cpu_mips_timer_update(CPUState *env)
{
uint64_t now, next;
@@ -64,6 +54,27 @@ static void cpu_mips_timer_update(CPUState *env)
qemu_mod_timer(env->timer, next);
}
+/* Expire the timer. */
+static void cpu_mips_timer_expire(CPUState *env)
+{
+ cpu_mips_timer_update(env);
+ if (env->insn_flags & ISA_MIPS32R2) {
+ env->CP0_Cause |= 1 << CP0Ca_TI;
+ }
+ qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
+}
+
+uint32_t cpu_mips_get_count (CPUState *env)
+{
+ if (env->CP0_Cause & (1 << CP0Ca_DC)) {
+ return env->CP0_Count;
+ } else {
+ return env->CP0_Count +
+ (uint32_t)muldiv64(qemu_get_clock(vm_clock),
+ TIMER_FREQ, get_ticks_per_sec());
+ }
+}
+
void cpu_mips_store_count (CPUState *env, uint32_t count)
{
if (env->CP0_Cause & (1 << CP0Ca_DC))
@@ -116,11 +127,8 @@ static void mips_timer_cb (void *opaque)
the comparator value. Offset the count by one to avoid immediately
retriggering the callback before any virtual time has passed. */
env->CP0_Count++;
- cpu_mips_timer_update(env);
+ cpu_mips_timer_expire(env);
env->CP0_Count--;
- if (env->insn_flags & ISA_MIPS32R2)
- env->CP0_Cause |= 1 << CP0Ca_TI;
- qemu_irq_raise(env->irq[(env->CP0_IntCtl >> CP0IntCtl_IPTI) & 0x7]);
}
void cpu_mips_clock_init (CPUState *env)
commit 4a6648f44eefbfbea38a1de56f8a8e44a8892941
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Mon Jan 17 20:26:30 2011 +0000
Replace 'extern inline' with 'static inline'
Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/tests/cris/check_abs.c b/tests/cris/check_abs.c
index 3966c87..9770a8d 100644
--- a/tests/cris/check_abs.c
+++ b/tests/cris/check_abs.c
@@ -4,13 +4,14 @@
#include "sys.h"
#include "crisutils.h"
-extern inline int cris_abs(int n) {
+static inline int cris_abs(int n)
+{
int r;
asm ("abs\t%1, %0\n" : "=r" (r) : "r" (n));
return r;
}
-extern inline void
+static inline void
verify_abs(int val, int res,
const int n, const int z, const int v, const int c)
{
diff --git a/tests/cris/check_addc.c b/tests/cris/check_addc.c
index e407855..facd1be 100644
--- a/tests/cris/check_addc.c
+++ b/tests/cris/check_addc.c
@@ -4,7 +4,8 @@
#include "sys.h"
#include "crisutils.h"
-extern inline int cris_addc(int a, const int b) {
+static inline int cris_addc(int a, const int b)
+{
asm ("addc\t%1, %0\n" : "+r" (a) : "r" (b));
return a;
}
diff --git a/tests/cris/check_addcm.c b/tests/cris/check_addcm.c
index 9ffea29..7928bc9 100644
--- a/tests/cris/check_addcm.c
+++ b/tests/cris/check_addcm.c
@@ -5,13 +5,15 @@
#include "crisutils.h"
/* need to avoid acr as source here. */
-extern inline int cris_addc_m(int a, const int *b) {
+static inline int cris_addc_m(int a, const int *b)
+{
asm volatile ("addc [%1], %0\n" : "+r" (a) : "r" (b));
return a;
}
/* 'b' is a crisv32 constrain to avoid postinc with $acr. */
-extern inline int cris_addc_pi_m(int a, int **b) {
+static inline int cris_addc_pi_m(int a, int **b)
+{
asm volatile ("addc [%1+], %0\n" : "+r" (a), "+b" (*b));
return a;
}
diff --git a/tests/cris/check_bound.c b/tests/cris/check_bound.c
index 411d2ad..e883175 100644
--- a/tests/cris/check_bound.c
+++ b/tests/cris/check_bound.c
@@ -4,19 +4,22 @@
#include "sys.h"
#include "crisutils.h"
-extern inline int cris_bound_b(int v, int b) {
+static inline int cris_bound_b(int v, int b)
+{
int r = v;
asm ("bound.b\t%1, %0\n" : "+r" (r) : "ri" (b));
return r;
}
-extern inline int cris_bound_w(int v, int b) {
+static inline int cris_bound_w(int v, int b)
+{
int r = v;
asm ("bound.w\t%1, %0\n" : "+r" (r) : "ri" (b));
return r;
}
-extern inline int cris_bound_d(int v, int b) {
+static inline int cris_bound_d(int v, int b)
+{
int r = v;
asm ("bound.d\t%1, %0\n" : "+r" (r) : "ri" (b));
return r;
diff --git a/tests/cris/check_ftag.c b/tests/cris/check_ftag.c
index 40d1507..908773a 100644
--- a/tests/cris/check_ftag.c
+++ b/tests/cris/check_ftag.c
@@ -4,19 +4,23 @@
#include "sys.h"
#include "crisutils.h"
-extern inline void cris_ftag_i(unsigned int x) {
+static inline void cris_ftag_i(unsigned int x)
+{
register unsigned int v asm("$r10") = x;
asm ("ftagi\t[%0]\n" : : "r" (v) );
}
-extern inline void cris_ftag_d(unsigned int x) {
+static inline void cris_ftag_d(unsigned int x)
+{
register unsigned int v asm("$r10") = x;
asm ("ftagd\t[%0]\n" : : "r" (v) );
}
-extern inline void cris_fidx_i(unsigned int x) {
+static inline void cris_fidx_i(unsigned int x)
+{
register unsigned int v asm("$r10") = x;
asm ("fidxi\t[%0]\n" : : "r" (v) );
}
-extern inline void cris_fidx_d(unsigned int x) {
+static inline void cris_fidx_d(unsigned int x)
+{
register unsigned int v asm("$r10") = x;
asm ("fidxd\t[%0]\n" : : "r" (v) );
}
diff --git a/tests/cris/check_int64.c b/tests/cris/check_int64.c
index 99ca6f1..fc60017 100644
--- a/tests/cris/check_int64.c
+++ b/tests/cris/check_int64.c
@@ -5,11 +5,13 @@
#include "crisutils.h"
-extern inline int64_t add64(const int64_t a, const int64_t b) {
+static inline int64_t add64(const int64_t a, const int64_t b)
+{
return a + b;
}
-extern inline int64_t sub64(const int64_t a, const int64_t b) {
+static inline int64_t sub64(const int64_t a, const int64_t b)
+{
return a - b;
}
diff --git a/tests/cris/check_lz.c b/tests/cris/check_lz.c
index 7b30a26..69c2e6d 100644
--- a/tests/cris/check_lz.c
+++ b/tests/cris/check_lz.c
@@ -3,7 +3,7 @@
#include <stdint.h>
#include "sys.h"
-extern inline int cris_lz(int x)
+static inline int cris_lz(int x)
{
int r;
asm ("lz\t%1, %0\n" : "=r" (r) : "r" (x));
diff --git a/tests/cris/check_swap.c b/tests/cris/check_swap.c
index 824a685..f851cbc 100644
--- a/tests/cris/check_swap.c
+++ b/tests/cris/check_swap.c
@@ -9,7 +9,7 @@
#define B 2
#define R 1
-extern inline int cris_swap(const int mode, int x)
+static inline int cris_swap(const int mode, int x)
{
switch (mode)
{
diff --git a/tests/cris/crisutils.h b/tests/cris/crisutils.h
index 7d1ea86..29b71cd 100644
--- a/tests/cris/crisutils.h
+++ b/tests/cris/crisutils.h
@@ -10,57 +10,57 @@ void _err(void) {
_fail(tst_cc_loc);
}
-extern inline void cris_tst_cc_n1(void)
+static inline void cris_tst_cc_n1(void)
{
asm volatile ("bpl _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_n0(void)
+static inline void cris_tst_cc_n0(void)
{
asm volatile ("bmi _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_z1(void)
+static inline void cris_tst_cc_z1(void)
{
asm volatile ("bne _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_z0(void)
+static inline void cris_tst_cc_z0(void)
{
asm volatile ("beq _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_v1(void)
+static inline void cris_tst_cc_v1(void)
{
asm volatile ("bvc _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_v0(void)
+static inline void cris_tst_cc_v0(void)
{
asm volatile ("bvs _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_c1(void)
+static inline void cris_tst_cc_c1(void)
{
asm volatile ("bcc _err\n"
"nop\n");
}
-extern inline void cris_tst_cc_c0(void)
+static inline void cris_tst_cc_c0(void)
{
asm volatile ("bcs _err\n"
"nop\n");
}
-extern inline void cris_tst_mov_cc(int n, int z)
+static inline void cris_tst_mov_cc(int n, int z)
{
if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
if (z) cris_tst_cc_z1(); else cris_tst_cc_z0();
asm volatile ("" : : "g" (_err));
}
-extern inline void cris_tst_cc(const int n, const int z,
+static inline void cris_tst_cc(const int n, const int z,
const int v, const int c)
{
if (n) cris_tst_cc_n1(); else cris_tst_cc_n0();
diff --git a/tests/hello-i386.c b/tests/hello-i386.c
index e00245d..86afc34 100644
--- a/tests/hello-i386.c
+++ b/tests/hello-i386.c
@@ -1,6 +1,6 @@
#include <asm/unistd.h>
-extern inline volatile void exit(int status)
+static inline volatile void exit(int status)
{
int __res;
__asm__ volatile ("movl %%ecx,%%ebx\n"\
@@ -8,7 +8,7 @@ extern inline volatile void exit(int status)
: "=a" (__res) : "0" (__NR_exit),"c" ((long)(status)));
}
-extern inline int write(int fd, const char * buf, int len)
+static inline int write(int fd, const char * buf, int len)
{
int status;
__asm__ volatile ("pushl %%ebx\n"\
commit 29718712eb2e53c09d28f08e39f6514d690f6fd3
Author: Stefan Weil <weil at mail.berlios.de>
Date: Sun Jan 16 16:28:20 2011 +0100
bsd-user: Fix possible memory leaks and wrong realloc call
These errors were reported by cppcheck:
[bsd-user/elfload.c:1108]: (error) Common realloc mistake: "syms" nulled but not freed upon failure
[bsd-user/elfload.c:1076]: (error) Memory leak: s
[bsd-user/elfload.c:1079]: (error) Memory leak: syms
v2:
* The previous fix for memory leaks was incomplete (thanks to Peter Maydell for te hint).
* Fix wrong realloc usage, too.
Cc: Blue Swirl <blauwirbel at gmail.com>
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 7374912..1ef1f97 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -1044,7 +1044,7 @@ static void load_symbols(struct elfhdr *hdr, int fd)
struct elf_shdr sechdr, symtab, strtab;
char *strings;
struct syminfo *s;
- struct elf_sym *syms;
+ struct elf_sym *syms, *new_syms;
lseek(fd, hdr->e_shoff, SEEK_SET);
for (i = 0; i < hdr->e_shnum; i++) {
@@ -1072,15 +1072,24 @@ static void load_symbols(struct elfhdr *hdr, int fd)
/* Now know where the strtab and symtab are. Snarf them. */
s = malloc(sizeof(*s));
syms = malloc(symtab.sh_size);
- if (!syms)
+ if (!syms) {
+ free(s);
return;
+ }
s->disas_strtab = strings = malloc(strtab.sh_size);
- if (!s->disas_strtab)
+ if (!s->disas_strtab) {
+ free(s);
+ free(syms);
return;
+ }
lseek(fd, symtab.sh_offset, SEEK_SET);
- if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
+ if (read(fd, syms, symtab.sh_size) != symtab.sh_size) {
+ free(s);
+ free(syms);
+ free(strings);
return;
+ }
nsyms = symtab.sh_size / sizeof(struct elf_sym);
@@ -1105,13 +1114,29 @@ static void load_symbols(struct elfhdr *hdr, int fd)
#endif
i++;
}
- syms = realloc(syms, nsyms * sizeof(*syms));
+
+ /* Attempt to free the storage associated with the local symbols
+ that we threw away. Whether or not this has any effect on the
+ memory allocation depends on the malloc implementation and how
+ many symbols we managed to discard. */
+ new_syms = realloc(syms, nsyms * sizeof(*syms));
+ if (new_syms == NULL) {
+ free(s);
+ free(syms);
+ free(strings);
+ return;
+ }
+ syms = new_syms;
qsort(syms, nsyms, sizeof(*syms), symcmp);
lseek(fd, strtab.sh_offset, SEEK_SET);
- if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
+ if (read(fd, strings, strtab.sh_size) != strtab.sh_size) {
+ free(s);
+ free(syms);
+ free(strings);
return;
+ }
s->disas_num_syms = nsyms;
#if ELF_CLASS == ELFCLASS32
s->disas_symtab.elf32 = syms;
commit 07d8a50cb0e096c5cdc5a81b8030e40833664dd3
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Mon Jan 17 19:29:33 2011 +0100
sm501: add 2D engine copyrect support
Linux kernel started to use the SM501 2D engine for the console, and
especially the copyrect operation.
Implement this operation so that recent kernels can be used with QEMU.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/sm501.c b/hw/sm501.c
index f16e6e4..388fc08 100644
--- a/hw/sm501.c
+++ b/hw/sm501.c
@@ -511,6 +511,7 @@ typedef struct SM501State {
uint32_t dc_crt_hwc_color_1_2;
uint32_t dc_crt_hwc_color_3;
+ uint32_t twoD_source;
uint32_t twoD_destination;
uint32_t twoD_dimension;
uint32_t twoD_control;
@@ -636,6 +637,9 @@ static void sm501_2d_operation(SM501State * s)
{
/* obtain operation parameters */
int operation = (s->twoD_control >> 16) & 0x1f;
+ int rtl = s->twoD_control & 0x8000000;
+ int src_x = (s->twoD_source >> 16) & 0x01FFF;
+ int src_y = s->twoD_source & 0xFFFF;
int dst_x = (s->twoD_destination >> 16) & 0x01FFF;
int dst_y = s->twoD_destination & 0xFFFF;
int operation_width = (s->twoD_dimension >> 16) & 0x1FFF;
@@ -645,10 +649,9 @@ static void sm501_2d_operation(SM501State * s)
int addressing = (s->twoD_stretch >> 16) & 0xF;
/* get frame buffer info */
-#if 0 /* for future use */
uint8_t * src = s->local_mem + (s->twoD_source_base & 0x03FFFFFF);
-#endif
uint8_t * dst = s->local_mem + (s->twoD_destination_base & 0x03FFFFFF);
+ int src_width = (s->dc_crt_h_total & 0x00000FFF) + 1;
int dst_width = (s->dc_crt_h_total & 0x00000FFF) + 1;
if (addressing != 0x0) {
@@ -663,8 +666,36 @@ static void sm501_2d_operation(SM501State * s)
}
switch (operation) {
- case 0x01: /* fill rectangle */
+ case 0x00: /* copy area */
+#define COPY_AREA(_bpp, _pixel_type, rtl) { \
+ int y, x, index_d, index_s; \
+ for (y = 0; y < operation_height; y++) { \
+ for (x = 0; x < operation_width; x++) { \
+ if (rtl) { \
+ index_s = ((src_y - y) * src_width + src_x - x) * _bpp; \
+ index_d = ((dst_y - y) * dst_width + dst_x - x) * _bpp; \
+ } else { \
+ index_s = ((src_y + y) * src_width + src_x + x) * _bpp; \
+ index_d = ((dst_y + y) * dst_width + dst_x + x) * _bpp; \
+ } \
+ *(_pixel_type*)&dst[index_d] = *(_pixel_type*)&src[index_s];\
+ } \
+ } \
+ }
+ switch (format_flags) {
+ case 0:
+ COPY_AREA(1, uint8_t, rtl);
+ break;
+ case 1:
+ COPY_AREA(2, uint16_t, rtl);
+ break;
+ case 2:
+ COPY_AREA(4, uint32_t, rtl);
+ break;
+ }
+ break;
+ case 0x01: /* fill rectangle */
#define FILL_RECT(_bpp, _pixel_type) { \
int y, x; \
for (y = 0; y < operation_height; y++) { \
@@ -1072,6 +1103,9 @@ static void sm501_2d_engine_write(void *opaque,
addr, value);
switch(addr) {
+ case SM501_2D_SOURCE:
+ s->twoD_source = value;
+ break;
case SM501_2D_DESTINATION:
s->twoD_destination = value;
break;
commit dc9121210eaf34e768901ffc6992dd13062c743a
Author: Alex Williamson <alex.williamson at redhat.com>
Date: Tue Jan 11 14:39:43 2011 -0700
savevm: Fix no_migrate
The no_migrate save state flag is currently only checked in the
last phase of migration. This means that we potentially waste
a lot of time and bandwidth with the live state handlers before
we ever check the no_migrate flags. The error message printed
when we catch a non-migratable device doesn't get printed for
a detached migration. And, no_migrate does nothing to prevent
an incoming migration to a target that includes a non-migratable
device. This attempts to fix all of these.
One notable difference in behavior is that an outgoing migration
now checks for non-migratable devices before ever connecting to
the target system. This means the target will remain listening
rather than exit from failure.
Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/migration.c b/migration.c
index e5ba51c..d593b1d 100644
--- a/migration.c
+++ b/migration.c
@@ -88,6 +88,10 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
return -1;
}
+ if (qemu_savevm_state_blocked(mon)) {
+ return -1;
+ }
+
if (strstart(uri, "tcp:", &p)) {
s = tcp_start_outgoing_migration(mon, p, max_throttle, detach,
blk, inc);
diff --git a/savevm.c b/savevm.c
index 90aa237..fcd8db4 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1401,19 +1401,13 @@ static int vmstate_load(QEMUFile *f, SaveStateEntry *se, int version_id)
return vmstate_load_state(f, se->vmsd, se->opaque, version_id);
}
-static int vmstate_save(QEMUFile *f, SaveStateEntry *se)
+static void vmstate_save(QEMUFile *f, SaveStateEntry *se)
{
- if (se->no_migrate) {
- return -1;
- }
-
if (!se->vmsd) { /* Old style */
se->save_state(f, se->opaque);
- return 0;
+ return;
}
vmstate_save_state(f,se->vmsd, se->opaque);
-
- return 0;
}
#define QEMU_VM_FILE_MAGIC 0x5145564d
@@ -1427,6 +1421,20 @@ static int vmstate_save(QEMUFile *f, SaveStateEntry *se)
#define QEMU_VM_SECTION_FULL 0x04
#define QEMU_VM_SUBSECTION 0x05
+bool qemu_savevm_state_blocked(Monitor *mon)
+{
+ SaveStateEntry *se;
+
+ QTAILQ_FOREACH(se, &savevm_handlers, entry) {
+ if (se->no_migrate) {
+ monitor_printf(mon, "state blocked by non-migratable device '%s'\n",
+ se->idstr);
+ return true;
+ }
+ }
+ return false;
+}
+
int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
int shared)
{
@@ -1508,7 +1516,6 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
{
SaveStateEntry *se;
- int r;
cpu_synchronize_all_states();
@@ -1541,11 +1548,7 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
qemu_put_be32(f, se->instance_id);
qemu_put_be32(f, se->version_id);
- r = vmstate_save(f, se);
- if (r < 0) {
- monitor_printf(mon, "cannot migrate with device '%s'\n", se->idstr);
- return r;
- }
+ vmstate_save(f, se);
}
qemu_put_byte(f, QEMU_VM_EOF);
@@ -1575,6 +1578,11 @@ static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
saved_vm_running = vm_running;
vm_stop(0);
+ if (qemu_savevm_state_blocked(mon)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
ret = qemu_savevm_state_begin(mon, f, 0, 0);
if (ret < 0)
goto out;
@@ -1692,6 +1700,10 @@ int qemu_loadvm_state(QEMUFile *f)
unsigned int v;
int ret;
+ if (qemu_savevm_state_blocked(default_mon)) {
+ return -EINVAL;
+ }
+
v = qemu_get_be32(f);
if (v != QEMU_VM_FILE_MAGIC)
return -EINVAL;
diff --git a/sysemu.h b/sysemu.h
index d8fceec..0c969f2 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -75,6 +75,7 @@ void qemu_announce_self(void);
void main_loop_wait(int nonblocking);
+bool qemu_savevm_state_blocked(Monitor *mon);
int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
int shared);
int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f);
commit 9e8a69cfd6f0fe2585528fc7a85110fc25c05d0b
Merge: 51f9b84... b36e391...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Mon Jan 17 09:49:38 2011 -0600
Merge remote branch 'mst/for_anthony' into staging
commit 668643b025dcff72b9b18adb5df794be9e9be5dc
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date: Tue Jan 11 14:20:39 2011 -0200
acpi_piix4: expose no_hotplug attribute via i/o port
Expose no_hotplug attribute via I/O port, so ACPI BIOS can indicate
removability status to guest OS.
An updated seabios is required to make use of this feature (seabios.git
commit ID 3c241edf3d7ef29c21).
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
Tested-by: Gleb Natapov <gleb at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 273097d..5bbc2b5 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -37,6 +37,7 @@
#define GPE_BASE 0xafe0
#define PCI_BASE 0xae00
#define PCI_EJ_BASE 0xae08
+#define PCI_RMV_BASE 0xae0c
#define PIIX4_PCI_HOTPLUG_STATUS 2
@@ -73,6 +74,7 @@ typedef struct PIIX4PMState {
/* for pci hotplug */
struct gpe_regs gpe;
struct pci_status pci0_status;
+ uint32_t pci0_hotplug_enable;
} PIIX4PMState;
static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s);
@@ -322,6 +324,25 @@ static const VMStateDescription vmstate_acpi = {
}
};
+static void piix4_update_hotplug(PIIX4PMState *s)
+{
+ PCIDevice *dev = &s->dev;
+ BusState *bus = qdev_get_parent_bus(&dev->qdev);
+ DeviceState *qdev, *next;
+
+ s->pci0_hotplug_enable = ~0;
+
+ QLIST_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
+ PCIDeviceInfo *info = container_of(qdev->info, PCIDeviceInfo, qdev);
+ PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, qdev);
+ int slot = PCI_SLOT(pdev->devfn);
+
+ if (info->no_hotplug) {
+ s->pci0_hotplug_enable &= ~(1 << slot);
+ }
+ }
+}
+
static void piix4_reset(void *opaque)
{
PIIX4PMState *s = opaque;
@@ -336,6 +357,7 @@ static void piix4_reset(void *opaque)
/* Mark SMM as already inited (until KVM supports SMM). */
pci_conf[0x5B] = 0x02;
}
+ piix4_update_hotplug(s);
}
static void piix4_powerdown(void *opaque, int irq, int power_failing)
@@ -576,6 +598,18 @@ static void pciej_write(void *opaque, uint32_t addr, uint32_t val)
PIIX4_DPRINTF("pciej write %x <== %d\n", addr, val);
}
+static uint32_t pcirmv_read(void *opaque, uint32_t addr)
+{
+ PIIX4PMState *s = opaque;
+
+ return s->pci0_hotplug_enable;
+}
+
+static void pcirmv_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ return;
+}
+
static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
PCIHotplugState state);
@@ -592,6 +626,9 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
register_ioport_write(PCI_EJ_BASE, 4, 4, pciej_write, bus);
register_ioport_read(PCI_EJ_BASE, 4, 4, pciej_read, bus);
+ register_ioport_write(PCI_RMV_BASE, 4, 4, pcirmv_write, s);
+ register_ioport_read(PCI_RMV_BASE, 4, 4, pcirmv_read, s);
+
pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
}
commit 9c046d96d4d0d1fef89a30b1491775492082da9d
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date: Tue Jan 11 14:20:38 2011 -0200
document QEMU<->ACPIBIOS PCI hotplug interface
Document how QEMU communicates with ACPI BIOS for PCI hotplug.
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/docs/specs/acpi_pci_hotplug.txt b/docs/specs/acpi_pci_hotplug.txt
new file mode 100644
index 0000000..f0f74a7
--- /dev/null
+++ b/docs/specs/acpi_pci_hotplug.txt
@@ -0,0 +1,37 @@
+QEMU<->ACPI BIOS PCI hotplug interface
+--------------------------------------
+
+QEMU supports PCI hotplug via ACPI, for PCI bus 0. This document
+describes the interface between QEMU and the ACPI BIOS.
+
+ACPI GPE block (IO ports 0xafe0-0xafe3, byte access):
+-----------------------------------------
+
+Generic ACPI GPE block. Bit 1 (GPE.1) used to notify PCI hotplug/eject
+event to ACPI BIOS, via SCI interrupt.
+
+PCI slot injection notification pending (IO port 0xae00-0xae03, 4-byte access):
+---------------------------------------------------------------
+Slot injection notification pending. One bit per slot.
+
+Read by ACPI BIOS GPE.1 handler to notify OS of injection
+events.
+
+PCI slot removal notification (IO port 0xae04-0xae07, 4-byte access):
+-----------------------------------------------------
+Slot removal notification pending. One bit per slot.
+
+Read by ACPI BIOS GPE.1 handler to notify OS of removal
+events.
+
+PCI device eject (IO port 0xae08-0xae0b, 4-byte access):
+----------------------------------------
+
+Used by ACPI BIOS _EJ0 method to request device removal. One bit per slot.
+Reads return 0.
+
+PCI removability status (IO port 0xae0c-0xae0f, 4-byte access):
+-----------------------------------------------
+
+Used by ACPI BIOS _RMV method to indicate removability status to OS. One
+bit per slot.
commit 51f9b84e759c692575542627dd8d39ae216ac521
Author: Hervé Poussineau <hpoussin at reactos.org>
Date: Sun Jan 2 19:44:49 2011 +0100
m48t59: Fix a wrong opaque passed to nvram read and write routines
This fixes boot on PPC prep.
Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/m48t59.c b/hw/m48t59.c
index 6991e2e..2020487 100644
--- a/hw/m48t59.c
+++ b/hw/m48t59.c
@@ -642,6 +642,7 @@ M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base,
DeviceState *dev;
SysBusDevice *s;
M48t59SysBusState *d;
+ M48t59State *state;
dev = qdev_create(NULL, "m48t59");
qdev_prop_set_uint32(dev, "type", type);
@@ -649,18 +650,18 @@ M48t59State *m48t59_init(qemu_irq IRQ, target_phys_addr_t mem_base,
qdev_prop_set_uint32(dev, "io_base", io_base);
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
+ d = FROM_SYSBUS(M48t59SysBusState, s);
+ state = &d->state;
sysbus_connect_irq(s, 0, IRQ);
if (io_base != 0) {
- register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s);
- register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s);
+ register_ioport_read(io_base, 0x04, 1, NVRAM_readb, state);
+ register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, state);
}
if (mem_base != 0) {
sysbus_mmio_map(s, 0, mem_base);
}
- d = FROM_SYSBUS(M48t59SysBusState, s);
-
- return &d->state;
+ return state;
}
M48t59State *m48t59_init_isa(uint32_t io_base, uint16_t size, int type)
commit e2af15b2ad57d3c61b79c8aea0871e3a00264e96
Author: Fabien Chouteau <chouteau at adacore.com>
Date: Thu Jan 13 12:46:57 2011 +0100
gdbstub: Close connection in gdb_exit
On Windows, this is required to flush the remaining data in the IO stream,
otherwise Gdb do not receive the last packet.
Version 2:
Fix linux-user build error.
Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
diff --git a/gdbstub.c b/gdbstub.c
index 0aa081b..d6556c9 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -2391,6 +2391,12 @@ void gdb_exit(CPUState *env, int code)
snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
put_packet(s, buf);
+
+#ifndef CONFIG_USER_ONLY
+ if (s->chr) {
+ qemu_chr_close(s->chr);
+ }
+#endif
}
#ifdef CONFIG_USER_ONLY
commit a8fb7ff3fdd05ffb4cce1ab4d3ff7768a490f2f5
Author: Michael Tokarev <mjt at tls.msk.ru>
Date: Mon Oct 18 16:55:25 2010 +0400
USB keyboard emulation key mapping error
The USB keyboard emulation's translation table in hw/usb-hid.c doesn't
match the codes actually sent for the Logo (a.k.a. "Windows") or Menu
keys. This results in the guest OS not being able to receive these keys
at all when the USB keyboard emulation is being used.
In particular, both the keymap in /usr/share/kvm/keymaps/modifiers and
the evdev table in x_keymap.c map these keys to 0xdb, 0xdc, and 0xdd,
while usb_hid_usage_keys[] seems to be expecting them to be mapped to
0x7d, 0x7e, and 0x7f.
The attached patch seems to fix the problem, at least in my (limited)
testing.
http://bugs.debian.org/578846
http://bugs.debian.org/600593 (cloned from the above against different pkg)
https://bugs.launchpad.net/qemu/+bug/584139
Signed-Off-By: Brad Jorsch <anomie at users.sourceforge.net>
Signed-Off-By: Michael Tokarev <mjt at tls.msk.ru>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 882d933..e8de301 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -399,7 +399,7 @@ static const uint8_t usb_hid_usage_keys[0x100] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
commit b2d9eda5d473fa7251319a368b0ee72d75218aed
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Thu Jan 13 08:20:39 2011 +0100
target-sh4: implement negc using TCG
Using setcond it's now possible to generate a relatively short negc
instruction in TCG.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/helper.h b/target-sh4/helper.h
index 4e595c8..2e52768 100644
--- a/target-sh4/helper.h
+++ b/target-sh4/helper.h
@@ -17,7 +17,6 @@ DEF_HELPER_2(addv, i32, i32, i32)
DEF_HELPER_2(addc, i32, i32, i32)
DEF_HELPER_2(subv, i32, i32, i32)
DEF_HELPER_2(subc, i32, i32, i32)
-DEF_HELPER_1(negc, i32, i32)
DEF_HELPER_2(div1, i32, i32, i32)
DEF_HELPER_2(macl, void, i32, i32)
DEF_HELPER_2(macw, void, i32, i32)
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index 9d7652f..30f9842 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -379,21 +379,6 @@ void helper_macw(uint32_t arg0, uint32_t arg1)
}
}
-uint32_t helper_negc(uint32_t arg)
-{
- uint32_t temp;
-
- temp = -arg;
- arg = temp - (env->sr & SR_T);
- if (0 < temp)
- env->sr |= SR_T;
- else
- env->sr &= ~SR_T;
- if (temp < arg)
- env->sr |= SR_T;
- return arg;
-}
-
uint32_t helper_subc(uint32_t arg0, uint32_t arg1)
{
uint32_t tmp0, tmp1;
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 743d76a..35573be 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -952,7 +952,21 @@ static void _decode_opc(DisasContext * ctx)
tcg_gen_neg_i32(REG(B11_8), REG(B7_4));
return;
case 0x600a: /* negc Rm,Rn */
- gen_helper_negc(REG(B11_8), REG(B7_4));
+ {
+ TCGv t0, t1;
+ t0 = tcg_temp_new();
+ tcg_gen_neg_i32(t0, REG(B7_4));
+ t1 = tcg_temp_new();
+ tcg_gen_andi_i32(t1, cpu_sr, SR_T);
+ tcg_gen_sub_i32(REG(B11_8), t0, t1);
+ tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
+ tcg_gen_setcond_i32(TCG_COND_GE, t1, REG(B11_8), t0);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
+ tcg_gen_setcondi_i32(TCG_COND_GE, t1, t0, 0);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+ }
return;
case 0x6007: /* not Rm,Rn */
tcg_gen_not_i32(REG(B11_8), REG(B7_4));
commit 2411fde9a41323310d472dd352006989f30049b2
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Thu Jan 13 08:20:39 2011 +0100
target-sh4: use rotl/rotr when possible
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index c8fffbc..743d76a 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1690,14 +1690,12 @@ static void _decode_opc(DisasContext * ctx)
}
return;
case 0x4004: /* rotl Rn */
- gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 31);
- tcg_gen_shli_i32(REG(B11_8), REG(B11_8), 1);
- gen_copy_bit_i32(REG(B11_8), 0, cpu_sr, 0);
+ tcg_gen_rotli_i32(REG(B11_8), REG(B11_8), 1);
+ gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
return;
case 0x4005: /* rotr Rn */
gen_copy_bit_i32(cpu_sr, 0, REG(B11_8), 0);
- tcg_gen_shri_i32(REG(B11_8), REG(B11_8), 1);
- gen_copy_bit_i32(REG(B11_8), 31, cpu_sr, 0);
+ tcg_gen_rotri_i32(REG(B11_8), REG(B11_8), 1);
return;
case 0x4000: /* shll Rn */
case 0x4020: /* shal Rn */
commit 4cd31ad264b11274f199bbd8e96474d8cde60c42
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sun Jan 16 08:32:27 2011 +0000
tcg/sparc64: fix segfault
With current OpenBSD, code_gen_buffer was mapped 8GB away from
text segment. Then any helpers were beyond the 2GB range of call
instruction genereated by TCG and so the calls would go nowhere,
leading to a segfault.
Fix by specifying an address for the code_gen_buffer,
hopefully free and nearby the helpers.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/exec.c b/exec.c
index 49c28b1..e950df2 100644
--- a/exec.c
+++ b/exec.c
@@ -531,6 +531,13 @@ static void code_gen_alloc(unsigned long tb_size)
/* Cannot map more than that */
if (code_gen_buffer_size > (800 * 1024 * 1024))
code_gen_buffer_size = (800 * 1024 * 1024);
+#elif defined(__sparc_v9__)
+ // Map the buffer below 2G, so we can use direct calls and branches
+ flags |= MAP_FIXED;
+ addr = (void *) 0x60000000UL;
+ if (code_gen_buffer_size > (512 * 1024 * 1024)) {
+ code_gen_buffer_size = (512 * 1024 * 1024);
+ }
#endif
code_gen_buffer = mmap(addr, code_gen_buffer_size,
PROT_WRITE | PROT_READ | PROT_EXEC,
commit 0c16e71e6a96a91e65c2a2e7b14b86423a21dd94
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Sat Jan 15 13:50:38 2011 +0100
target-sh4: correct use of ! and &
Fix wrong usage of ! and & in MMU related functions. Thanks to Blue
Swirl for reporting the issue.
Reported-by: Blue Swirl <blauwirbel at gmail.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 2343366..45449ea 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -380,7 +380,7 @@ static int get_mmu_address(CPUState * env, target_ulong * physical,
MMU_DTLB_VIOLATION_READ;
} else if ((rw == 1) && !(matching->pr & 1)) {
n = MMU_DTLB_VIOLATION_WRITE;
- } else if ((rw == 1) & !matching->d) {
+ } else if ((rw == 1) && !matching->d) {
n = MMU_DTLB_INITIAL_WRITE;
} else {
*prot = PAGE_READ;
@@ -430,7 +430,7 @@ static int get_physical_address(CPUState * env, target_ulong * physical,
}
/* If MMU is disabled, return the corresponding physical page */
- if (!env->mmucr & MMUCR_AT) {
+ if (!(env->mmucr & MMUCR_AT)) {
*physical = address & 0x1FFFFFFF;
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
return MMU_OK;
commit 2d5b50749adeda4e45066290deec19aa8e2322c3
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Jan 15 08:31:00 2011 +0000
monitor: fix a typo
Fix usage of wrong variable, spotted by clang:
/src/qemu/monitor.c:2278:36: warning: The left operand of '&' is a garbage value
prot = pde & (PG_USER_MASK | PG_RW_MASK |
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/monitor.c b/monitor.c
index f258000..d291158 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2275,8 +2275,8 @@ static void mem_info_64(Monitor *mon, CPUState *env)
end = (l1 << 39) + (l2 << 30);
if (pdpe & PG_PRESENT_MASK) {
if (pdpe & PG_PSE_MASK) {
- prot = pde & (PG_USER_MASK | PG_RW_MASK |
- PG_PRESENT_MASK);
+ prot = pdpe & (PG_USER_MASK | PG_RW_MASK |
+ PG_PRESENT_MASK);
mem_print(mon, &start, &last_prot, end, prot);
} else {
pd_addr = pdpe & 0x3fffffffff000ULL;
commit 0601740a5db12ea7ae0f2f7826f0cfb05854500a
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Dec 30 12:04:57 2010 +0000
make_device_config: Fix non-fatal error message with dash and other shells
ORS=" " adds a blank to the name of the include file.
Some shells (e.g. dash) don't accept input redirection
(tr -d '\r' < $f) when $f ends with a blank, so they
print an error message instead of reading pci.mak.
This is a non-fatal error because pci.mak does not
contain an include line. It was introduced by commit
5d6b423c5cd6f9dfac30959ff1d5c088996719c3.
Using printf avoids adding a blank and is also supported
by older awk versions (this solution was suggested by
Paolo Bonzini, thank you).
Cc: Blue Swirl <blauwirbel at gmail.com>
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Tested-by: Andreas Färber <andreas.faerber at web.de>
diff --git a/make_device_config.sh b/make_device_config.sh
index 596fc5b..5d14885 100644
--- a/make_device_config.sh
+++ b/make_device_config.sh
@@ -18,7 +18,7 @@ process_includes () {
f=$src
while [ -n "$f" ] ; do
- f=`tr -d '\r' < $f | awk '/^include / {ORS=" "; print "'$src_dir'/" $2}'`
+ f=`tr -d '\r' < $f | awk '/^include / {printf "'$src_dir'/%s", $2}'`
[ $? = 0 ] || exit 1
all_includes="$all_includes $f"
done
commit 42f5a7e9367c1f2cadea3b5af8cccc2781c442df
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:19 2011 +0100
MAINTAINERS: add entries for TCG
The MAINTAINERS file was lacking entries concerning the TCG code, add
them based on the git history.
For the common TCG code, is probably better to keep qemu-devel at non-gnu.org
as this code can break easily, so it's better to get it reviewed by a few
persons.
Acked-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/MAINTAINERS b/MAINTAINERS
index 3f15b21..98db322 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -426,3 +426,56 @@ Linux user
M: Riku Voipio <riku.voipio at iki.fi>
S: Maintained
F: linux-user/
+
+Tiny Code Generator (TCG)
+-------------------------
+Common code
+M: qemu-devel at nongnu.org
+S: Maintained
+F: tcg/
+
+ARM target
+M: Andrzej Zaborowski <balrogg at gmail.com>
+S: Maintained
+F: tcg/arm/
+
+HPPA target
+M: Richard Henderson <rth at twiddle.net>
+S: Maintained
+F: tcg/hppa/
+
+i386 target
+M: qemu-devel at nongnu.org
+S: Maintained
+F: tcg/i386/
+
+IA64 target
+M: Aurelien Jarno <aurelien at aurel32.net>
+S: Maintained
+F: tcg/ia64/
+
+MIPS target
+M: Aurelien Jarno <aurelien at aurel32.ne>
+S: Maintained
+F: tcg/mips/
+
+PPC
+M: Vassili Karpov (malc) <av1474 at comtv.ru>
+S: Maintained
+F: tcg/ppc/
+
+PPC64 target
+M: Vassili Karpov (malc) <av1474 at comtv.ru>
+S: Maintained
+F: tcg/ppc64/
+
+S390 target
+M: Alexander Graf <agraf at suse.de>
+M: Richard Henderson <rth at twiddle.net>
+S: Maintained
+F: tcg/s390/
+
+SPARC target
+M: Blue Swirl <blauwirbel at gmail.com>
+S: Maintained
+F: tcg/sparc/
commit ddb13561ac49e1cf496fab61cf18a4a60b32d3a5
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:19 2011 +0100
MAINTAINERS: Change MIPS and SH4 maintainers
Since nobody else seems interested in maintaining MIPS and SH4 targets,
and as I have done most of the recent code changes, let officialize
that.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/MAINTAINERS b/MAINTAINERS
index 98af4ab..3f15b21 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -81,8 +81,8 @@ S: Maintained
F: target-microblaze/
MIPS
-M: qemu-devel at nongnu.org
-S: Orphan
+M: Aurelien Jarno <aurelien at aurel32.net>
+S: Maintained
F: target-mips/
PowerPC
@@ -96,8 +96,8 @@ S: Maintained
F: target-s390x/
SH4
-M: qemu-devel at nongnu.org
-S: Orphan
+M: Aurelien Jarno <aurelien at aurel32.net>
+S: Maintained
F: target-sh4/
SPARC
commit afcacd536e1c12d357520302e1bb7add115918e5
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:19 2011 +0100
MAINTAINERS: fix typos
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/MAINTAINERS b/MAINTAINERS
index 59effc7..98af4ab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -202,7 +202,7 @@ M: Edgar E. Iglesias <edgar.iglesias at gmail.com>
S: Maintained
F: hw/etraxfs.c
-M86K Machines
+M68K Machines
-------------
an5206
M: Paul Brook <paul at codesourcery.com>
@@ -279,7 +279,7 @@ F: hw/r2d.c
Shix
M: Magnus Damm <magnus.damm at gmail.com>
-S: Oprhan
+S: Orphan
F: hw/shix.c
SPARC Machines
commit e12ce78d4aa05ccf80d6a843a9227042647db39d
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:19 2011 +0100
target-arm: Restore IT bits when resuming after an exception
We were not correctly restoring the IT bits when resuming execution
after taking an unexpected exception in the middle of an IT block.
Fix this by tracking them along with PC changes and restoring in
gen_pc_load().
This fixes bug https://bugs.launchpad.net/qemu/+bug/581335
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 946f767..907d73a 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -64,6 +64,8 @@ typedef struct DisasContext {
int vec_stride;
} DisasContext;
+static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
+
#if defined(CONFIG_USER_ONLY)
#define IS_USER(s) 1
#else
@@ -9109,6 +9111,38 @@ static inline void gen_intermediate_code_internal(CPUState *env,
max_insns = CF_COUNT_MASK;
gen_icount_start();
+
+ /* A note on handling of the condexec (IT) bits:
+ *
+ * We want to avoid the overhead of having to write the updated condexec
+ * bits back to the CPUState for every instruction in an IT block. So:
+ * (1) if the condexec bits are not already zero then we write
+ * zero back into the CPUState now. This avoids complications trying
+ * to do it at the end of the block. (For example if we don't do this
+ * it's hard to identify whether we can safely skip writing condexec
+ * at the end of the TB, which we definitely want to do for the case
+ * where a TB doesn't do anything with the IT state at all.)
+ * (2) if we are going to leave the TB then we call gen_set_condexec()
+ * which will write the correct value into CPUState if zero is wrong.
+ * This is done both for leaving the TB at the end, and for leaving
+ * it because of an exception we know will happen, which is done in
+ * gen_exception_insn(). The latter is necessary because we need to
+ * leave the TB with the PC/IT state just prior to execution of the
+ * instruction which caused the exception.
+ * (3) if we leave the TB unexpectedly (eg a data abort on a load)
+ * then the CPUState will be wrong and we need to reset it.
+ * This is handled in the same way as restoration of the
+ * PC in these situations: we will be called again with search_pc=1
+ * and generate a mapping of the condexec bits for each PC in
+ * gen_opc_condexec_bits[]. gen_pc_load[] then uses this to restore
+ * the condexec bits.
+ *
+ * Note that there are no instructions which can read the condexec
+ * bits, and none which can write non-static values to them, so
+ * we don't need to care about whether CPUState is correct in the
+ * middle of a TB.
+ */
+
/* Reset the conditional execution bits immediately. This avoids
complications trying to do it at the end of the block. */
if (dc->condexec_mask || dc->condexec_cond)
@@ -9157,6 +9191,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
gen_opc_instr_start[lj++] = 0;
}
gen_opc_pc[lj] = dc->pc;
+ gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
gen_opc_instr_start[lj] = 1;
gen_opc_icount[lj] = num_insns;
}
@@ -9364,4 +9399,5 @@ void gen_pc_load(CPUState *env, TranslationBlock *tb,
unsigned long searched_pc, int pc_pos, void *puc)
{
env->regs[15] = gen_opc_pc[pc_pos];
+ env->condexec_bits = gen_opc_condexec_bits[pc_pos];
}
commit 964413d9d96ab81ee6bf81b176c767342aa90db9
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:19 2011 +0100
linux-user: ARM: clear the IT bits when invoking a signal handler
When invoking a signal handler for an ARM target, make sure the IT
bits in the CPSR are cleared. (This would otherwise cause incorrect
execution if the IT state was non-zero when an exception occured.
This bug has been masked previously because we weren't getting the
IT state bits at exception entry right anyway.)
Also use the proper cpsr_read()/cpsr_write() interface to update
the CPSR rather than manipulating CPUState fields directly.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/signal.c b/linux-user/signal.c
index c846b8c..0664770 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1256,6 +1256,14 @@ setup_return(CPUState *env, struct target_sigaction *ka,
abi_ulong handler = ka->_sa_handler;
abi_ulong retcode;
int thumb = handler & 1;
+ uint32_t cpsr = cpsr_read(env);
+
+ cpsr &= ~CPSR_IT;
+ if (thumb) {
+ cpsr |= CPSR_T;
+ } else {
+ cpsr &= ~CPSR_T;
+ }
if (ka->sa_flags & TARGET_SA_RESTORER) {
retcode = ka->sa_restorer;
@@ -1278,13 +1286,7 @@ setup_return(CPUState *env, struct target_sigaction *ka,
env->regs[13] = frame_addr;
env->regs[14] = retcode;
env->regs[15] = handler & (thumb ? ~1 : ~3);
- env->thumb = thumb;
-
-#if 0
-#ifdef TARGET_CONFIG_CPU_32
- env->cpsr = cpsr;
-#endif
-#endif
+ cpsr_write(env, cpsr, 0xffffffff);
return 0;
}
commit bc4a0de0a2c891b8daba4806baf9f11436f5f562
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:19 2011 +0100
target-arm: Refactor translation of exception generating instructions
Create a new function which does the common sequence of gen_set_condexec,
gen_set_pc_im, gen_exception, set is_jmp to DISAS_JUMP.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 74b9657..946f767 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3485,6 +3485,14 @@ gen_set_condexec (DisasContext *s)
}
}
+static void gen_exception_insn(DisasContext *s, int offset, int excp)
+{
+ gen_set_condexec(s);
+ gen_set_pc_im(s->pc - offset);
+ gen_exception(excp);
+ s->is_jmp = DISAS_JUMP;
+}
+
static void gen_nop_hint(DisasContext *s, int val)
{
switch (val) {
@@ -5976,10 +5984,7 @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
tcg_gen_mov_i32(cpu_exclusive_test, addr);
tcg_gen_movi_i32(cpu_exclusive_info,
size | (rd << 4) | (rt << 8) | (rt2 << 12));
- gen_set_condexec(s);
- gen_set_pc_im(s->pc - 4);
- gen_exception(EXCP_STREX);
- s->is_jmp = DISAS_JUMP;
+ gen_exception_insn(s, 4, EXCP_STREX);
}
#else
static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
@@ -6376,10 +6381,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
goto illegal_op;
}
/* bkpt */
- gen_set_condexec(s);
- gen_set_pc_im(s->pc - 4);
- gen_exception(EXCP_BKPT);
- s->is_jmp = DISAS_JUMP;
+ gen_exception_insn(s, 4, EXCP_BKPT);
break;
case 0x8: /* signed multiply */
case 0xa:
@@ -7278,10 +7280,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
break;
default:
illegal_op:
- gen_set_condexec(s);
- gen_set_pc_im(s->pc - 4);
- gen_exception(EXCP_UDEF);
- s->is_jmp = DISAS_JUMP;
+ gen_exception_insn(s, 4, EXCP_UDEF);
break;
}
}
@@ -8927,10 +8926,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
break;
case 0xe: /* bkpt */
- gen_set_condexec(s);
- gen_set_pc_im(s->pc - 2);
- gen_exception(EXCP_BKPT);
- s->is_jmp = DISAS_JUMP;
+ gen_exception_insn(s, 2, EXCP_BKPT);
break;
case 0xa: /* rev */
@@ -9052,17 +9048,11 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
}
return;
undef32:
- gen_set_condexec(s);
- gen_set_pc_im(s->pc - 4);
- gen_exception(EXCP_UDEF);
- s->is_jmp = DISAS_JUMP;
+ gen_exception_insn(s, 4, EXCP_UDEF);
return;
illegal_op:
undef:
- gen_set_condexec(s);
- gen_set_pc_im(s->pc - 2);
- gen_exception(EXCP_UDEF);
- s->is_jmp = DISAS_JUMP;
+ gen_exception_insn(s, 2, EXCP_UDEF);
}
/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
@@ -9150,10 +9140,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
if (bp->pc == dc->pc) {
- gen_set_condexec(dc);
- gen_set_pc_im(dc->pc);
- gen_exception(EXCP_DEBUG);
- dc->is_jmp = DISAS_JUMP;
+ gen_exception_insn(dc, 0, EXCP_DEBUG);
/* Advance PC so that clearing the breakpoint will
invalidate this TB. */
dc->pc += 2;
commit 5de3a9d3b72a9aebc126caee95fe515a900130bf
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:19 2011 +0100
target-arm: Remove redundant setting of IT bits before Thumb SWI
Remove a redundant call to gen_set_condexec() in the translation of Thumb
mode SWI. (SWI and WFI generate "exceptions" which happen after the
execution of the instruction, ie when PC and IT bits have updated.
So the condexec bits at this point are not correct. However, the code
that handles finishing the translation of the TB will write the correct
value of the condexec bits later, so the only effect was that a conditional
Thumb SWI would generate slightly worse code than necessary.)
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 10bd545..74b9657 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9016,7 +9016,6 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
if (cond == 0xf) {
/* swi */
- gen_set_condexec(s);
gen_set_pc_im(s->pc);
s->is_jmp = DISAS_SWI;
break;
commit 61f74d6a290d606504e4fbd6a94cbee3ce277533
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:19 2011 +0100
target-arm: Translate with user-state from TB flags, not CPUState
When translating, get the user/priv state from the TB flags, not
the CPUState.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 0e28ffd..10bd545 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9099,11 +9099,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
#if !defined(CONFIG_USER_ONLY)
- if (IS_M(env)) {
- dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
- } else {
- dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
- }
+ dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
#endif
dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
commit 05ed9a991987fd2f117914f9b0f7157553837d1b
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:19 2011 +0100
target-arm: Set privileged bit in TB flags correctly for M profile
M profile ARM cores don't have a CPSR mode field. Set the bit in the
TB flags that indicates non-user mode correctly for these cores.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 07b92d6..5bcd53a 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -485,13 +485,19 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
{
+ int privmode;
*pc = env->regs[15];
*cs_base = 0;
*flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
| (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
| (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
| (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT);
- if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
+ if (arm_feature(env, ARM_FEATURE_M)) {
+ privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1));
+ } else {
+ privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR;
+ }
+ if (privmode) {
*flags |= ARM_TBFLAG_PRIV_MASK;
}
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
commit 98eac7cab4392ab28fa22265e27906f5b9c6c9da
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:19 2011 +0100
target-arm: Translate with condexec bits from TB flags, not CPUState
When translating, the condexec bits for the TB are in the TB flags;
the CPUState condexec bits may be different.
This patch fixes https://bugs.launchpad.net/bugs/604872 where we might
segfault if we took an exception in the middle of a TB with an IT
block, because when we came to retranslate in cpu_restore_state()
the CPUState condexec bits would have advanced compared to the start
of the TB and we would generate different (wrong) code.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 45f8e3e..0e28ffd 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9096,8 +9096,8 @@ static inline void gen_intermediate_code_internal(CPUState *env,
dc->singlestep_enabled = env->singlestep_enabled;
dc->condjmp = 0;
dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
- dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
- dc->condexec_cond = env->condexec_bits >> 4;
+ dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
+ dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
#if !defined(CONFIG_USER_ONLY)
if (IS_M(env)) {
dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
@@ -9126,7 +9126,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
gen_icount_start();
/* Reset the conditional execution bits immediately. This avoids
complications trying to do it at the end of the block. */
- if (env->condexec_bits)
+ if (dc->condexec_mask || dc->condexec_cond)
{
TCGv tmp = new_tmp();
tcg_gen_movi_i32(tmp, 0);
commit 7204ab889f1cf5b09026af22185525edbee07a97
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:19 2011 +0100
target-arm: Translate with Thumb state from TB flags, not CPUState
The Thumb/ARM state for the TB being translated should come from
the TB flags, not the CPUState.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index e15d10b..45f8e3e 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -9095,7 +9095,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
dc->pc = pc_start;
dc->singlestep_enabled = env->singlestep_enabled;
dc->condjmp = 0;
- dc->thumb = env->thumb;
+ dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
dc->condexec_cond = env->condexec_bits >> 4;
#if !defined(CONFIG_USER_ONLY)
@@ -9182,7 +9182,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
- if (env->thumb) {
+ if (dc->thumb) {
disas_thumb_insn(env, dc);
if (dc->condexec_mask) {
dc->condexec_cond = (dc->condexec_cond & 0xe)
@@ -9296,7 +9296,7 @@ done_generating:
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log("----------------\n");
qemu_log("IN: %s\n", lookup_symbol(pc_start));
- log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
+ log_target_disas(pc_start, dc->pc - pc_start, dc->thumb);
qemu_log("\n");
}
#endif
commit 69d1fc221a0bcd6a9a17e79ab933ab7525f15973
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:19 2011 +0100
target-arm: Translate with VFP len/stride from TB flags, not CPUState
When translating, the VFP vector length and stride for this TB are encoded
in the TB flags; the CPUState copies may be different and must not be used.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index f8e3616..e15d10b 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -60,6 +60,8 @@ typedef struct DisasContext {
int user;
#endif
int vfp_enabled;
+ int vec_len;
+ int vec_stride;
} DisasContext;
#if defined(CONFIG_USER_ONLY)
@@ -2895,7 +2897,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
rm = VFP_SREG_M(insn);
}
- veclen = env->vfp.vec_len;
+ veclen = s->vec_len;
if (op == 15 && rn > 3)
veclen = 0;
@@ -2916,9 +2918,9 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
veclen = 0;
} else {
if (dp)
- delta_d = (env->vfp.vec_stride >> 1) + 1;
+ delta_d = (s->vec_stride >> 1) + 1;
else
- delta_d = env->vfp.vec_stride + 1;
+ delta_d = s->vec_stride + 1;
if ((rm & bank_mask) == 0) {
/* mixed scalar/vector */
@@ -9104,6 +9106,8 @@ static inline void gen_intermediate_code_internal(CPUState *env,
}
#endif
dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
+ dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
+ dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
cpu_F0s = tcg_temp_new_i32();
cpu_F1s = tcg_temp_new_i32();
cpu_F0d = tcg_temp_new_i64();
commit 5df8bac1d3ea43b7f55ffab07cbc6d81a37d82ab
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:19 2011 +0100
target-arm: Translate with VFP-enabled from TB flags, not CPUState
When translating code, whether the VFP unit is enabled for this TB
is stored in a bit in the TB flags. Use this rather than incorrectly
reading the FPEXC from the CPUState passed to translation.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index ee19d76..f8e3616 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -59,6 +59,7 @@ typedef struct DisasContext {
#if !defined(CONFIG_USER_ONLY)
int user;
#endif
+ int vfp_enabled;
} DisasContext;
#if defined(CONFIG_USER_ONLY)
@@ -2603,12 +2604,6 @@ static void gen_vfp_msr(TCGv tmp)
dead_tmp(tmp);
}
-static inline int
-vfp_enabled(CPUState * env)
-{
- return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
-}
-
static void gen_neon_dup_u8(TCGv var, int shift)
{
TCGv tmp = new_tmp();
@@ -2653,7 +2648,7 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
if (!arm_feature(env, ARM_FEATURE_VFP))
return 1;
- if (!vfp_enabled(env)) {
+ if (!s->vfp_enabled) {
/* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
if ((insn & 0x0fe00fff) != 0x0ee00a10)
return 1;
@@ -3804,7 +3799,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
TCGv tmp2;
TCGv_i64 tmp64;
- if (!vfp_enabled(env))
+ if (!s->vfp_enabled)
return 1;
VFP_DREG_D(rd, insn);
rn = (insn >> 16) & 0xf;
@@ -4199,7 +4194,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
TCGv tmp, tmp2, tmp3, tmp4, tmp5;
TCGv_i64 tmp64;
- if (!vfp_enabled(env))
+ if (!s->vfp_enabled)
return 1;
q = (insn & (1 << 6)) != 0;
u = (insn >> 24) & 1;
@@ -9108,6 +9103,7 @@ static inline void gen_intermediate_code_internal(CPUState *env,
dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
}
#endif
+ dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
cpu_F0s = tcg_temp_new_i32();
cpu_F1s = tcg_temp_new_i32();
cpu_F0d = tcg_temp_new_i64();
commit a170576856fedfcdd7d8602cb5650a33d13d38f5
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:18 2011 +0100
target-arm: Add symbolic constants for bitfields in TB flags
Add symbolic constants for the bitfields we use in the TB flags.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index e501cf5..07b92d6 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -453,17 +453,50 @@ static inline void cpu_clone_regs(CPUState *env, target_ulong newsp)
#include "cpu-all.h"
+/* Bit usage in the TB flags field: */
+#define ARM_TBFLAG_THUMB_SHIFT 0
+#define ARM_TBFLAG_THUMB_MASK (1 << ARM_TBFLAG_THUMB_SHIFT)
+#define ARM_TBFLAG_VECLEN_SHIFT 1
+#define ARM_TBFLAG_VECLEN_MASK (0x7 << ARM_TBFLAG_VECLEN_SHIFT)
+#define ARM_TBFLAG_VECSTRIDE_SHIFT 4
+#define ARM_TBFLAG_VECSTRIDE_MASK (0x3 << ARM_TBFLAG_VECSTRIDE_SHIFT)
+#define ARM_TBFLAG_PRIV_SHIFT 6
+#define ARM_TBFLAG_PRIV_MASK (1 << ARM_TBFLAG_PRIV_SHIFT)
+#define ARM_TBFLAG_VFPEN_SHIFT 7
+#define ARM_TBFLAG_VFPEN_MASK (1 << ARM_TBFLAG_VFPEN_SHIFT)
+#define ARM_TBFLAG_CONDEXEC_SHIFT 8
+#define ARM_TBFLAG_CONDEXEC_MASK (0xff << ARM_TBFLAG_CONDEXEC_SHIFT)
+/* Bits 31..16 are currently unused. */
+
+/* some convenience accessor macros */
+#define ARM_TBFLAG_THUMB(F) \
+ (((F) & ARM_TBFLAG_THUMB_MASK) >> ARM_TBFLAG_THUMB_SHIFT)
+#define ARM_TBFLAG_VECLEN(F) \
+ (((F) & ARM_TBFLAG_VECLEN_MASK) >> ARM_TBFLAG_VECLEN_SHIFT)
+#define ARM_TBFLAG_VECSTRIDE(F) \
+ (((F) & ARM_TBFLAG_VECSTRIDE_MASK) >> ARM_TBFLAG_VECSTRIDE_SHIFT)
+#define ARM_TBFLAG_PRIV(F) \
+ (((F) & ARM_TBFLAG_PRIV_MASK) >> ARM_TBFLAG_PRIV_SHIFT)
+#define ARM_TBFLAG_VFPEN(F) \
+ (((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT)
+#define ARM_TBFLAG_CONDEXEC(F) \
+ (((F) & ARM_TBFLAG_CONDEXEC_MASK) >> ARM_TBFLAG_CONDEXEC_SHIFT)
+
static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
target_ulong *cs_base, int *flags)
{
*pc = env->regs[15];
*cs_base = 0;
- *flags = env->thumb | (env->vfp.vec_len << 1)
- | (env->vfp.vec_stride << 4) | (env->condexec_bits << 8);
- if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
- *flags |= (1 << 6);
- if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
- *flags |= (1 << 7);
+ *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
+ | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
+ | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
+ | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT);
+ if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
+ *flags |= ARM_TBFLAG_PRIV_MASK;
+ }
+ if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) {
+ *flags |= ARM_TBFLAG_VFPEN_MASK;
+ }
}
#endif
commit 39ea3d4eaf1ff300ee55946108394729bc053dfa
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:18 2011 +0100
target-arm: Don't generate code specific to current CPU mode for SRS
When translating the SRS instruction, handle the "store registers
to stack of current mode" case in the helper function rather than
inline. This means the generated code does not make assumptions
about the current CPU mode which might not be valid when the TB
is executed later.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 8186500..b562767 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1849,12 +1849,20 @@ bad_reg:
void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val)
{
- env->banked_r13[bank_number(mode)] = val;
+ if ((env->uncached_cpsr & CPSR_M) == mode) {
+ env->regs[13] = val;
+ } else {
+ env->banked_r13[bank_number(mode)] = val;
+ }
}
uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode)
{
- return env->banked_r13[bank_number(mode)];
+ if ((env->uncached_cpsr & CPSR_M) == mode) {
+ return env->regs[13];
+ } else {
+ return env->banked_r13[bank_number(mode)];
+ }
}
uint32_t HELPER(v7m_mrs)(CPUState *env, uint32_t reg)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 57664bc..ee19d76 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6122,14 +6122,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
goto illegal_op;
ARCH(6);
op1 = (insn & 0x1f);
- if (op1 == (env->uncached_cpsr & CPSR_M)) {
- addr = load_reg(s, 13);
- } else {
- addr = new_tmp();
- tmp = tcg_const_i32(op1);
- gen_helper_get_r13_banked(addr, cpu_env, tmp);
- tcg_temp_free_i32(tmp);
- }
+ addr = new_tmp();
+ tmp = tcg_const_i32(op1);
+ gen_helper_get_r13_banked(addr, cpu_env, tmp);
+ tcg_temp_free_i32(tmp);
i = (insn >> 23) & 3;
switch (i) {
case 0: offset = -4; break; /* DA */
@@ -6156,14 +6152,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
}
if (offset)
tcg_gen_addi_i32(addr, addr, offset);
- if (op1 == (env->uncached_cpsr & CPSR_M)) {
- store_reg(s, 13, addr);
- } else {
- tmp = tcg_const_i32(op1);
- gen_helper_set_r13_banked(cpu_env, tmp, addr);
- tcg_temp_free_i32(tmp);
- dead_tmp(addr);
- }
+ tmp = tcg_const_i32(op1);
+ gen_helper_set_r13_banked(cpu_env, tmp, addr);
+ tcg_temp_free_i32(tmp);
+ dead_tmp(addr);
} else {
dead_tmp(addr);
}
@@ -7575,14 +7567,10 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
} else {
/* srs */
op = (insn & 0x1f);
- if (op == (env->uncached_cpsr & CPSR_M)) {
- addr = load_reg(s, 13);
- } else {
- addr = new_tmp();
- tmp = tcg_const_i32(op);
- gen_helper_get_r13_banked(addr, cpu_env, tmp);
- tcg_temp_free_i32(tmp);
- }
+ addr = new_tmp();
+ tmp = tcg_const_i32(op);
+ gen_helper_get_r13_banked(addr, cpu_env, tmp);
+ tcg_temp_free_i32(tmp);
if ((insn & (1 << 24)) == 0) {
tcg_gen_addi_i32(addr, addr, -8);
}
@@ -7598,13 +7586,9 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
} else {
tcg_gen_addi_i32(addr, addr, 4);
}
- if (op == (env->uncached_cpsr & CPSR_M)) {
- store_reg(s, 13, addr);
- } else {
- tmp = tcg_const_i32(op);
- gen_helper_set_r13_banked(cpu_env, tmp, addr);
- tcg_temp_free_i32(tmp);
- }
+ tmp = tcg_const_i32(op);
+ gen_helper_set_r13_banked(cpu_env, tmp, addr);
+ tcg_temp_free_i32(tmp);
} else {
dead_tmp(addr);
}
commit 718269667ab60c878940ab7a4e3e0ef1e984d784
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:18 2011 +0100
target-arm: Use the standard FPSCR value for VRSQRTS
VSQRTS always uses the standard FPSCR value as it is a Neon instruction.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/helper.c b/target-arm/helper.c
index d779055..8186500 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2616,7 +2616,7 @@ float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)
{
- float_status *s = &env->vfp.fp_status;
+ float_status *s = &env->vfp.standard_fp_status;
float32 two = int32_to_float32(2, s);
float32 three = int32_to_float32(3, s);
float32 product;
commit 3a492f3a606642879637d50777444d82440c9f5c
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:18 2011 +0100
target-arm: Add support for 'Standard FPSCR Value' as used by Neon
Add support to the ARM helper routines for a second fp_status value
which should be used for operations which the ARM ARM indicates use
"ARM standard floating-point arithmetic" rather than being controlled
by the rounding/flush/NaN settings in the FPSCR.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 340933e..e501cf5 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -173,7 +173,20 @@ typedef struct CPUARMState {
/* scratch space when Tn are not sufficient. */
uint32_t scratch[8];
+ /* fp_status is the "normal" fp status. standard_fp_status retains
+ * values corresponding to the ARM "Standard FPSCR Value", ie
+ * default-NaN, flush-to-zero, round-to-nearest and is used by
+ * any operations (generally Neon) which the architecture defines
+ * as controlled by the standard FPSCR value rather than the FPSCR.
+ *
+ * To avoid having to transfer exception bits around, we simply
+ * say that the FPSCR cumulative exception flags are the logical
+ * OR of the flags in the two fp statuses. This relies on the
+ * only thing which needs to read the exception flags being
+ * an explicit FPSCR read.
+ */
float_status fp_status;
+ float_status standard_fp_status;
} vfp;
uint32_t exclusive_addr;
uint32_t exclusive_val;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index ac47de0..d779055 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -237,6 +237,9 @@ void cpu_reset(CPUARMState *env)
env->vfp.xregs[ARM_VFP_FPEXC] = 0;
env->cp15.c2_base_mask = 0xffffc000u;
#endif
+ set_flush_to_zero(1, &env->vfp.standard_fp_status);
+ set_flush_inputs_to_zero(1, &env->vfp.standard_fp_status);
+ set_default_nan_mode(1, &env->vfp.standard_fp_status);
tlb_flush(env, 1);
}
@@ -2256,6 +2259,7 @@ uint32_t HELPER(vfp_get_fpscr)(CPUState *env)
| (env->vfp.vec_len << 16)
| (env->vfp.vec_stride << 20);
i = get_float_exception_flags(&env->vfp.fp_status);
+ i |= get_float_exception_flags(&env->vfp.standard_fp_status);
fpscr |= vfp_exceptbits_from_host(i);
return fpscr;
}
@@ -2323,6 +2327,7 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
i = vfp_exceptbits_to_host(val);
set_float_exception_flags(i, &env->vfp.fp_status);
+ set_float_exception_flags(0, &env->vfp.standard_fp_status);
}
void vfp_set_fpscr(CPUState *env, uint32_t val)
commit 9ea62f571ce8953dba1d2bad2bdeaf9c3a84b7d7
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:18 2011 +0100
target-arm: Fix implementation of VRSQRTS
The implementation of the ARM VRSQRTS instruction (which calculates
(3 - op1 * op2) / 2) was missing the division operation. It also
did not handle the special cases of (0,inf) and (inf,0).
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 705b99f..ac47de0 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2612,8 +2612,16 @@ float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUState *env)
{
float_status *s = &env->vfp.fp_status;
+ float32 two = int32_to_float32(2, s);
float32 three = int32_to_float32(3, s);
- return float32_sub(three, float32_mul(a, b, s), s);
+ float32 product;
+ if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
+ (float32_is_infinity(b) && float32_is_zero_or_denormal(a))) {
+ product = float32_zero;
+ } else {
+ product = float32_mul(a, b, s);
+ }
+ return float32_div(float32_sub(three, product, s), two, s);
}
/* NEON helpers. */
commit 6f3300ad2b5a1e7090720993d9fcb9f550259e12
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Fri Jan 14 20:39:18 2011 +0100
softfloat: Add float32_is_zero_or_denormal() function
Add a utility function to softfloat to test whether a float32
is zero or denormal.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index a6d0f16..4a5345c 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -336,6 +336,11 @@ INLINE int float32_is_any_nan(float32 a)
return ((float32_val(a) & ~(1 << 31)) > 0x7f800000UL);
}
+INLINE int float32_is_zero_or_denormal(float32 a)
+{
+ return (float32_val(a) & 0x7f800000) == 0;
+}
+
#define float32_zero make_float32(0)
#define float32_one make_float32(0x3f800000)
#define float32_ln2 make_float32(0x3f317218)
commit 3bd4be3ada596bbed81fe955c963bb6a64335011
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:18 2011 +0100
lsi53c895a: fix endianness issues
lsi_ram_read*() and lsi_ram_write*() are not consistent, one uses
leXX_to_cpu() the other uses nothing. As the comment above the RAM
declaration says: "Script ram is stored as 32-bit words in host
byteorder.", remove the leXX_to_cpu() calls.
This fixes the boot of an ARM versatile machine on MIPS and PowerPC
hosts.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 0129ae3..9c761cd 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -1930,7 +1930,7 @@ static uint32_t lsi_ram_readw(void *opaque, target_phys_addr_t addr)
val = s->script_ram[addr >> 2];
if (addr & 2)
val >>= 16;
- return le16_to_cpu(val);
+ return val;
}
static uint32_t lsi_ram_readl(void *opaque, target_phys_addr_t addr)
@@ -1938,7 +1938,7 @@ static uint32_t lsi_ram_readl(void *opaque, target_phys_addr_t addr)
LSIState *s = opaque;
addr &= 0x1fff;
- return le32_to_cpu(s->script_ram[addr >> 2]);
+ return s->script_ram[addr >> 2];
}
static CPUReadMemoryFunc * const lsi_ram_readfn[3] = {
commit d30df5cec94cc165d76ccabb0d1847357178795e
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:18 2011 +0100
mips/malta: fix board id
Board id can't be written with stl_phys() as it's read-only part of
memory. Use stl_p() on the memory buffer instead.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 5ef3fcb..d3ba969 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -910,7 +910,7 @@ void mips_malta_init (ram_addr_t ram_size,
/* Board ID = 0x420 (Malta Board with CoreLV)
XXX: theoretically 0x1e000010 should map to flash and 0x1fc00010 should
map to the board ID. */
- stl_phys(0x1fc00010LL, 0x00000420);
+ stl_p(qemu_get_ram_ptr(bios_offset) + 0x10, 0x00000420);
/* Init internal devices */
cpu_mips_irq_init_cpu(env);
commit c5c191370e82e3f27a7b3c6616544b39b7487410
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:18 2011 +0100
target-sh4: use setcond when possible
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index b3cbe91..c8fffbc 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -381,26 +381,26 @@ static inline void gen_clr_t(void)
static inline void gen_cmp(int cond, TCGv t0, TCGv t1)
{
- int label1 = gen_new_label();
- int label2 = gen_new_label();
- tcg_gen_brcond_i32(cond, t1, t0, label1);
- gen_clr_t();
- tcg_gen_br(label2);
- gen_set_label(label1);
- gen_set_t();
- gen_set_label(label2);
+ TCGv t;
+
+ t = tcg_temp_new();
+ tcg_gen_setcond_i32(cond, t, t1, t0);
+ tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, t);
+
+ tcg_temp_free(t);
}
static inline void gen_cmp_imm(int cond, TCGv t0, int32_t imm)
{
- int label1 = gen_new_label();
- int label2 = gen_new_label();
- tcg_gen_brcondi_i32(cond, t0, imm, label1);
- gen_clr_t();
- tcg_gen_br(label2);
- gen_set_label(label1);
- gen_set_t();
- gen_set_label(label2);
+ TCGv t;
+
+ t = tcg_temp_new();
+ tcg_gen_setcondi_i32(cond, t, t0, imm);
+ tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, t);
+
+ tcg_temp_free(t);
}
static inline void gen_store_flags(uint32_t flags)
@@ -816,24 +816,22 @@ static void _decode_opc(DisasContext * ctx)
return;
case 0x200c: /* cmp/str Rm,Rn */
{
- int label1 = gen_new_label();
- int label2 = gen_new_label();
- TCGv cmp1 = tcg_temp_local_new();
- TCGv cmp2 = tcg_temp_local_new();
+ TCGv cmp1 = tcg_temp_new();
+ TCGv cmp2 = tcg_temp_new();
+ tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
tcg_gen_xor_i32(cmp1, REG(B7_4), REG(B11_8));
tcg_gen_andi_i32(cmp2, cmp1, 0xff000000);
- tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
+ tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
tcg_gen_andi_i32(cmp2, cmp1, 0x00ff0000);
- tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
+ tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
tcg_gen_andi_i32(cmp2, cmp1, 0x0000ff00);
- tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
+ tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
tcg_gen_andi_i32(cmp2, cmp1, 0x000000ff);
- tcg_gen_brcondi_i32(TCG_COND_EQ, cmp2, 0, label1);
- tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
- tcg_gen_br(label2);
- gen_set_label(label1);
- tcg_gen_ori_i32(cpu_sr, cpu_sr, SR_T);
- gen_set_label(label2);
+ tcg_gen_setcondi_i32(TCG_COND_EQ, cmp2, cmp2, 0);
+ tcg_gen_or_i32(cpu_sr, cpu_sr, cmp2);
tcg_temp_free(cmp2);
tcg_temp_free(cmp1);
}
commit be15c50d8e20edf9338c689764e6398ccec92ed9
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:18 2011 +0100
target-sh4: log instructions start in TCG code
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 65ea7f6..b3cbe91 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1892,6 +1892,10 @@ static void decode_opc(DisasContext * ctx)
{
uint32_t old_flags = ctx->flags;
+ if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
+ tcg_gen_debug_insn_start(ctx->pc);
+ }
+
_decode_opc(ctx);
if (old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
commit 6f396c8f38fb47dda5622880f7f2c646b145bc23
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:18 2011 +0100
target-sh4: simplify comparisons after a 'and' op
When a TCG variable is anded with a value and the compared with the same
value, we can simply invert the comparison and compare it with 0. The
generated code is smaller.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 04bc94a..65ea7f6 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -332,7 +332,7 @@ static inline void gen_branch_slot(uint32_t delayed_pc, int t)
tcg_gen_movi_i32(cpu_delayed_pc, delayed_pc);
sr = tcg_temp_new();
tcg_gen_andi_i32(sr, cpu_sr, SR_T);
- tcg_gen_brcondi_i32(TCG_COND_NE, sr, t ? SR_T : 0, label);
+ tcg_gen_brcondi_i32(t ? TCG_COND_EQ:TCG_COND_NE, sr, 0, label);
tcg_gen_ori_i32(cpu_flags, cpu_flags, DELAY_SLOT_TRUE);
gen_set_label(label);
}
@@ -347,7 +347,7 @@ static void gen_conditional_jump(DisasContext * ctx,
l1 = gen_new_label();
sr = tcg_temp_new();
tcg_gen_andi_i32(sr, cpu_sr, SR_T);
- tcg_gen_brcondi_i32(TCG_COND_EQ, sr, SR_T, l1);
+ tcg_gen_brcondi_i32(TCG_COND_NE, sr, 0, l1);
gen_goto_tb(ctx, 0, ifnott);
gen_set_label(l1);
gen_goto_tb(ctx, 1, ift);
@@ -362,7 +362,7 @@ static void gen_delayed_conditional_jump(DisasContext * ctx)
l1 = gen_new_label();
ds = tcg_temp_new();
tcg_gen_andi_i32(ds, cpu_flags, DELAY_SLOT_TRUE);
- tcg_gen_brcondi_i32(TCG_COND_EQ, ds, DELAY_SLOT_TRUE, l1);
+ tcg_gen_brcondi_i32(TCG_COND_NE, ds, 0, l1);
gen_goto_tb(ctx, 1, ctx->pc + 2);
gen_set_label(l1);
tcg_gen_andi_i32(cpu_flags, cpu_flags, ~DELAY_SLOT_TRUE);
commit 4f6493ff8a73bbb24ad81b080cc256c1c896b7fb
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:18 2011 +0100
target-sh4: fix reset on r2d
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/r2d.c b/hw/r2d.c
index c4f32ef..90d1af2 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -208,6 +208,20 @@ static int r2d_pci_map_irq(PCIDevice *d, int irq_num)
return intx[d->devfn >> 3];
}
+typedef struct ResetData {
+ CPUState *env;
+ uint32_t vector;
+} ResetData;
+
+static void main_cpu_reset(void *opaque)
+{
+ ResetData *s = (ResetData *)opaque;
+ CPUState *env = s->env;
+
+ cpu_reset(env);
+ env->pc = s->vector;
+}
+
static struct __attribute__((__packed__))
{
int mount_root_rdonly;
@@ -228,6 +242,7 @@ static void r2d_init(ram_addr_t ram_size,
const char *initrd_filename, const char *cpu_model)
{
CPUState *env;
+ ResetData *reset_info;
struct SH7750State *s;
ram_addr_t sdram_addr;
qemu_irq *irq;
@@ -242,6 +257,10 @@ static void r2d_init(ram_addr_t ram_size,
fprintf(stderr, "Unable to find CPU definition\n");
exit(1);
}
+ reset_info = qemu_mallocz(sizeof(ResetData));
+ reset_info->env = env;
+ reset_info->vector = env->pc;
+ qemu_register_reset(main_cpu_reset, reset_info);
/* Allocate memory space */
sdram_addr = qemu_ram_alloc(NULL, "r2d.sdram", SDRAM_SIZE);
@@ -290,7 +309,7 @@ static void r2d_init(ram_addr_t ram_size,
/* initialization which should be done by firmware */
stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */
stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */
- env->pc = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
+ reset_info->vector = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */
}
if (initrd_filename) {
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index fe33b8a..95df6d2 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -136,8 +136,6 @@ typedef struct memory_content {
} memory_content;
typedef struct CPUSH4State {
- int id; /* CPU model */
-
uint32_t flags; /* general execution flags */
uint32_t gregs[24]; /* general registers */
float32 fregs[32]; /* floating point registers */
@@ -173,14 +171,18 @@ typedef struct CPUSH4State {
uint32_t expevt; /* exception event register */
uint32_t intevt; /* interrupt event register */
+ tlb_t itlb[ITLB_SIZE]; /* instruction translation table */
+ tlb_t utlb[UTLB_SIZE]; /* unified translation table */
+
+ uint32_t ldst;
+
+ CPU_COMMON
+
+ int id; /* CPU model */
uint32_t pvr; /* Processor Version Register */
uint32_t prr; /* Processor Revision Register */
uint32_t cvr; /* Cache Version Register */
- uint32_t ldst;
-
- CPU_COMMON tlb_t utlb[UTLB_SIZE]; /* unified translation table */
- tlb_t itlb[ITLB_SIZE]; /* instruction translation table */
void *intc_handle;
int intr_at_halt; /* SR_BL ignored during sleep */
memory_content *movcal_backup;
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 69d507d..04bc94a 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -185,30 +185,27 @@ void cpu_dump_state(CPUState * env, FILE * f,
}
}
-static void cpu_sh4_reset(CPUSH4State * env)
+void cpu_reset(CPUSH4State * env)
{
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
log_cpu_state(env, 0);
}
-#if defined(CONFIG_USER_ONLY)
- env->sr = 0;
-#else
- env->sr = SR_MD | SR_RB | SR_BL | SR_I3 | SR_I2 | SR_I1 | SR_I0;
-#endif
- env->vbr = 0;
+ memset(env, 0, offsetof(CPUSH4State, breakpoints));
+ tlb_flush(env, 1);
+
env->pc = 0xA0000000;
#if defined(CONFIG_USER_ONLY)
env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
#else
+ env->sr = SR_MD | SR_RB | SR_BL | SR_I3 | SR_I2 | SR_I1 | SR_I0;
env->fpscr = FPSCR_DN | FPSCR_RM_ZERO; /* CPU reset value according to SH4 manual */
set_float_rounding_mode(float_round_to_zero, &env->fp_status);
set_flush_to_zero(1, &env->fp_status);
#endif
set_default_nan_mode(1, &env->fp_status);
- env->mmucr = 0;
}
typedef struct {
@@ -267,7 +264,7 @@ void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf)
(*cpu_fprintf)(f, "%s\n", sh4_defs[i].name);
}
-static void cpu_sh4_register(CPUSH4State *env, const sh4_def_t *def)
+static void cpu_register(CPUSH4State *env, const sh4_def_t *def)
{
env->pvr = def->pvr;
env->prr = def->prr;
@@ -289,9 +286,8 @@ CPUSH4State *cpu_sh4_init(const char *cpu_model)
env->movcal_backup_tail = &(env->movcal_backup);
sh4_translate_init();
env->cpu_model_str = cpu_model;
- cpu_sh4_reset(env);
- cpu_sh4_register(env, def);
- tlb_flush(env, 1);
+ cpu_reset(env);
+ cpu_register(env, def);
qemu_init_vcpu(env);
return env;
}
commit fd4bab102c14171f8a5a6b04def6434b75a658a2
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:18 2011 +0100
target-sh4: optimize exceptions
As exception is not the normal path, don't bother saving PC, before
raising one, instead rely on code retranslation to get the CPU state.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index 525b060..9d7652f 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -83,28 +83,31 @@ void helper_ldtlb(void)
#endif
}
-void helper_raise_illegal_instruction(void)
+static inline void raise_exception(int index, void *retaddr)
{
- env->exception_index = 0x180;
+ env->exception_index = index;
+ cpu_restore_state_from_retaddr(retaddr);
cpu_loop_exit();
}
+void helper_raise_illegal_instruction(void)
+{
+ raise_exception(0x180, GETPC());
+}
+
void helper_raise_slot_illegal_instruction(void)
{
- env->exception_index = 0x1a0;
- cpu_loop_exit();
+ raise_exception(0x1a0, GETPC());
}
void helper_raise_fpu_disable(void)
{
- env->exception_index = 0x800;
- cpu_loop_exit();
+ raise_exception(0x800, GETPC());
}
void helper_raise_slot_fpu_disable(void)
{
- env->exception_index = 0x820;
- cpu_loop_exit();
+ raise_exception(0x820, GETPC());
}
void helper_debug(void)
@@ -124,8 +127,7 @@ void helper_sleep(uint32_t next_pc)
void helper_trapa(uint32_t tra)
{
env->tra = tra << 2;
- env->exception_index = 0x160;
- cpu_loop_exit();
+ raise_exception(0x160, GETPC());
}
void helper_movcal(uint32_t address, uint32_t value)
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 65b6ea4..69d507d 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -471,7 +471,6 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
#define CHECK_NOT_DELAY_SLOT \
if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
{ \
- tcg_gen_movi_i32(cpu_pc, ctx->pc); \
gen_helper_raise_slot_illegal_instruction(); \
ctx->bstate = BS_EXCP; \
return; \
@@ -479,7 +478,6 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
#define CHECK_PRIVILEGED \
if (IS_USER(ctx)) { \
- tcg_gen_movi_i32(cpu_pc, ctx->pc); \
if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
gen_helper_raise_slot_illegal_instruction(); \
} else { \
@@ -491,7 +489,6 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
#define CHECK_FPU_ENABLED \
if (ctx->flags & SR_FD) { \
- tcg_gen_movi_i32(cpu_pc, ctx->pc); \
if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
gen_helper_raise_slot_fpu_disable(); \
} else { \
@@ -1380,7 +1377,6 @@ static void _decode_opc(DisasContext * ctx)
{
TCGv imm;
CHECK_NOT_DELAY_SLOT
- tcg_gen_movi_i32(cpu_pc, ctx->pc);
imm = tcg_const_i32(B7_0);
gen_helper_trapa(imm);
tcg_temp_free(imm);
@@ -1888,7 +1884,6 @@ static void _decode_opc(DisasContext * ctx)
ctx->opcode, ctx->pc);
fflush(stderr);
#endif
- tcg_gen_movi_i32(cpu_pc, ctx->pc);
if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
gen_helper_raise_slot_illegal_instruction();
} else {
commit 17075f10ff9e2c8bd59ecbf9569421e437707e43
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:18 2011 +0100
target-sh4: add ftrv instruction
Add the ftrv XMTRX,FVn instruction, which computes the 4-row x 4-column
matrix XMTRX by the 4-dimensional vector FVn.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/helper.h b/target-sh4/helper.h
index 544031c..4e595c8 100644
--- a/target-sh4/helper.h
+++ b/target-sh4/helper.h
@@ -50,5 +50,6 @@ DEF_HELPER_1(fsqrt_DT, i64, i64)
DEF_HELPER_1(ftrc_FT, i32, i32)
DEF_HELPER_1(ftrc_DT, i32, i64)
DEF_HELPER_2(fipr, void, i32, i32)
+DEF_HELPER_1(ftrv, void, i32)
#include "def-helper.h"
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index 030f60d..525b060 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -802,3 +802,29 @@ void helper_fipr(uint32_t m, uint32_t n)
env->fregs[bank + n + 3] = r;
}
+
+void helper_ftrv(uint32_t n)
+{
+ int bank_matrix, bank_vector;
+ int i, j;
+ float32 r[4];
+ float32 p;
+
+ bank_matrix = (env->sr & FPSCR_FR) ? 0 : 16;
+ bank_vector = (env->sr & FPSCR_FR) ? 16 : 0;
+ set_float_exception_flags(0, &env->fp_status);
+ for (i = 0 ; i < 4 ; i++) {
+ r[i] = float32_zero;
+ for (j = 0 ; j < 4 ; j++) {
+ p = float32_mul(env->fregs[bank_matrix + 4 * j + i],
+ env->fregs[bank_vector + j],
+ &env->fp_status);
+ r[i] = float32_add(r[i], p, &env->fp_status);
+ }
+ }
+ update_fpscr(GETPC());
+
+ for (i = 0 ; i < 4 ; i++) {
+ env->fregs[bank_vector + i] = r[i];
+ }
+}
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 557550f..65b6ea4 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1871,6 +1871,17 @@ static void _decode_opc(DisasContext * ctx)
return;
}
break;
+ case 0xf0fd: /* ftrv XMTRX,FVn */
+ CHECK_FPU_ENABLED
+ if ((ctx->opcode & 0x0300) == 0x0100 &&
+ (ctx->fpscr & FPSCR_PR) == 0) {
+ TCGv n;
+ n = tcg_const_i32((ctx->opcode >> 18) & 3);
+ gen_helper_ftrv(n);
+ tcg_temp_free(n);
+ return;
+ }
+ break;
}
#if 0
fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
commit af8c2bde4b4d4111e5bf49417b74069ce8750435
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:18 2011 +0100
target-sh4: add fipr instruction
Add the fipr FVm,FVn instruction, which computes the inner products of
a 4-dimensional single precision floating-point vector.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/helper.h b/target-sh4/helper.h
index 4b2fcdd..544031c 100644
--- a/target-sh4/helper.h
+++ b/target-sh4/helper.h
@@ -49,5 +49,6 @@ DEF_HELPER_1(fsqrt_FT, i32, i32)
DEF_HELPER_1(fsqrt_DT, i64, i64)
DEF_HELPER_1(ftrc_FT, i32, i32)
DEF_HELPER_1(ftrc_DT, i32, i64)
+DEF_HELPER_2(fipr, void, i32, i32)
#include "def-helper.h"
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index aea0eb1..030f60d 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -782,3 +782,23 @@ uint32_t helper_ftrc_DT(uint64_t t0)
update_fpscr(GETPC());
return ret;
}
+
+void helper_fipr(uint32_t m, uint32_t n)
+{
+ int bank, i;
+ float32 r, p;
+
+ bank = (env->sr & FPSCR_FR) ? 16 : 0;
+ r = float32_zero;
+ set_float_exception_flags(0, &env->fp_status);
+
+ for (i = 0 ; i < 4 ; i++) {
+ p = float32_mul(env->fregs[bank + m + i],
+ env->fregs[bank + n + i],
+ &env->fp_status);
+ r = float32_add(r, p, &env->fp_status);
+ }
+ update_fpscr(GETPC());
+
+ env->fregs[bank + n + 3] = r;
+}
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 8b2f1fc..557550f 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -1859,6 +1859,18 @@ static void _decode_opc(DisasContext * ctx)
tcg_temp_free_i64(fp);
}
return;
+ case 0xf0ed: /* fipr FVm,FVn */
+ CHECK_FPU_ENABLED
+ if ((ctx->fpscr & FPSCR_PR) == 0) {
+ TCGv m, n;
+ m = tcg_const_i32((ctx->opcode >> 16) & 3);
+ n = tcg_const_i32((ctx->opcode >> 18) & 3);
+ gen_helper_fipr(m, n);
+ tcg_temp_free(m);
+ tcg_temp_free(n);
+ return;
+ }
+ break;
}
#if 0
fprintf(stderr, "unknown instruction 0x%04x at pc 0x%08x\n",
commit 21829e9b39e3aa0874931aa6981f258c82f41715
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:18 2011 +0100
target-sh4: implement FPU exceptions
FPU exception support where not implemented on SH4. Implement them by
clearing the softfloat exceptions flags before an FP instruction (the
SH4 FPU also clear them before an instruction), and calling a function
to update the FPSCR register after an FP instruction. This function
update the corresponding FPSCR bits (both flags and cumulative flags)
and trigger exception if enabled.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index 9025a29..aea0eb1 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -21,6 +21,22 @@
#include "exec.h"
#include "helper.h"
+static void cpu_restore_state_from_retaddr(void *retaddr)
+{
+ TranslationBlock *tb;
+ unsigned long pc;
+
+ if (retaddr) {
+ pc = (unsigned long) retaddr;
+ 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, NULL);
+ }
+ }
+}
+
#ifndef CONFIG_USER_ONLY
#define MMUSUFFIX _mmu
@@ -39,9 +55,7 @@
void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
{
- TranslationBlock *tb;
CPUState *saved_env;
- unsigned long pc;
int ret;
/* XXX: hack to restore env in all cases, even if not called from
@@ -50,16 +64,8 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
env = cpu_single_env;
ret = cpu_sh4_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
if (ret) {
- if (retaddr) {
- /* now we have a real cpu fault */
- pc = (unsigned long) retaddr;
- 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, NULL);
- }
- }
+ /* now we have a real cpu fault */
+ cpu_restore_state_from_retaddr(retaddr);
cpu_loop_exit();
}
env = saved_env;
@@ -452,6 +458,47 @@ void helper_ld_fpscr(uint32_t val)
set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
}
+static void update_fpscr(void *retaddr)
+{
+ int xcpt, cause, enable;
+
+ xcpt = get_float_exception_flags(&env->fp_status);
+
+ /* Clear the flag entries */
+ env->fpscr &= ~FPSCR_FLAG_MASK;
+
+ if (unlikely(xcpt)) {
+ if (xcpt & float_flag_invalid) {
+ env->fpscr |= FPSCR_FLAG_V;
+ }
+ if (xcpt & float_flag_divbyzero) {
+ env->fpscr |= FPSCR_FLAG_Z;
+ }
+ if (xcpt & float_flag_overflow) {
+ env->fpscr |= FPSCR_FLAG_O;
+ }
+ if (xcpt & float_flag_underflow) {
+ env->fpscr |= FPSCR_FLAG_U;
+ }
+ if (xcpt & float_flag_inexact) {
+ env->fpscr |= FPSCR_FLAG_I;
+ }
+
+ /* Accumulate in cause entries */
+ env->fpscr |= (env->fpscr & FPSCR_FLAG_MASK)
+ << (FPSCR_CAUSE_SHIFT - FPSCR_FLAG_SHIFT);
+
+ /* Generate an exception if enabled */
+ cause = (env->fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT;
+ enable = (env->fpscr & FPSCR_ENABLE_MASK) >> FPSCR_ENABLE_SHIFT;
+ if (cause & enable) {
+ cpu_restore_state_from_retaddr(retaddr);
+ env->exception_index = 0x120;
+ cpu_loop_exit();
+ }
+ }
+}
+
uint32_t helper_fabs_FT(uint32_t t0)
{
CPU_FloatU f;
@@ -473,7 +520,9 @@ uint32_t helper_fadd_FT(uint32_t t0, uint32_t t1)
CPU_FloatU f0, f1;
f0.l = t0;
f1.l = t1;
+ set_float_exception_flags(0, &env->fp_status);
f0.f = float32_add(f0.f, f1.f, &env->fp_status);
+ update_fpscr(GETPC());
return f0.l;
}
@@ -482,56 +531,82 @@ uint64_t helper_fadd_DT(uint64_t t0, uint64_t t1)
CPU_DoubleU d0, d1;
d0.ll = t0;
d1.ll = t1;
+ set_float_exception_flags(0, &env->fp_status);
d0.d = float64_add(d0.d, d1.d, &env->fp_status);
+ update_fpscr(GETPC());
return d0.ll;
}
void helper_fcmp_eq_FT(uint32_t t0, uint32_t t1)
{
CPU_FloatU f0, f1;
+ int relation;
f0.l = t0;
f1.l = t1;
- if (float32_compare(f0.f, f1.f, &env->fp_status) == 0)
+ set_float_exception_flags(0, &env->fp_status);
+ relation = float32_compare(f0.f, f1.f, &env->fp_status);
+ if (unlikely(relation == float_relation_unordered)) {
+ update_fpscr(GETPC());
+ } else if (relation == float_relation_equal) {
set_t();
- else
+ } else {
clr_t();
+ }
}
void helper_fcmp_eq_DT(uint64_t t0, uint64_t t1)
{
CPU_DoubleU d0, d1;
+ int relation;
d0.ll = t0;
d1.ll = t1;
- if (float64_compare(d0.d, d1.d, &env->fp_status) == 0)
+ set_float_exception_flags(0, &env->fp_status);
+ relation = float64_compare(d0.d, d1.d, &env->fp_status);
+ if (unlikely(relation == float_relation_unordered)) {
+ update_fpscr(GETPC());
+ } else if (relation == float_relation_equal) {
set_t();
- else
+ } else {
clr_t();
+ }
}
void helper_fcmp_gt_FT(uint32_t t0, uint32_t t1)
{
CPU_FloatU f0, f1;
+ int relation;
f0.l = t0;
f1.l = t1;
- if (float32_compare(f0.f, f1.f, &env->fp_status) == 1)
+ set_float_exception_flags(0, &env->fp_status);
+ relation = float32_compare(f0.f, f1.f, &env->fp_status);
+ if (unlikely(relation == float_relation_unordered)) {
+ update_fpscr(GETPC());
+ } else if (relation == float_relation_greater) {
set_t();
- else
+ } else {
clr_t();
+ }
}
void helper_fcmp_gt_DT(uint64_t t0, uint64_t t1)
{
CPU_DoubleU d0, d1;
+ int relation;
d0.ll = t0;
d1.ll = t1;
- if (float64_compare(d0.d, d1.d, &env->fp_status) == 1)
+ set_float_exception_flags(0, &env->fp_status);
+ relation = float64_compare(d0.d, d1.d, &env->fp_status);
+ if (unlikely(relation == float_relation_unordered)) {
+ update_fpscr(GETPC());
+ } else if (relation == float_relation_greater) {
set_t();
- else
+ } else {
clr_t();
+ }
}
uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
@@ -539,7 +614,9 @@ uint64_t helper_fcnvsd_FT_DT(uint32_t t0)
CPU_DoubleU d;
CPU_FloatU f;
f.l = t0;
+ set_float_exception_flags(0, &env->fp_status);
d.d = float32_to_float64(f.f, &env->fp_status);
+ update_fpscr(GETPC());
return d.ll;
}
@@ -548,7 +625,9 @@ uint32_t helper_fcnvds_DT_FT(uint64_t t0)
CPU_DoubleU d;
CPU_FloatU f;
d.ll = t0;
+ set_float_exception_flags(0, &env->fp_status);
f.f = float64_to_float32(d.d, &env->fp_status);
+ update_fpscr(GETPC());
return f.l;
}
@@ -557,7 +636,9 @@ uint32_t helper_fdiv_FT(uint32_t t0, uint32_t t1)
CPU_FloatU f0, f1;
f0.l = t0;
f1.l = t1;
+ set_float_exception_flags(0, &env->fp_status);
f0.f = float32_div(f0.f, f1.f, &env->fp_status);
+ update_fpscr(GETPC());
return f0.l;
}
@@ -566,21 +647,29 @@ uint64_t helper_fdiv_DT(uint64_t t0, uint64_t t1)
CPU_DoubleU d0, d1;
d0.ll = t0;
d1.ll = t1;
+ set_float_exception_flags(0, &env->fp_status);
d0.d = float64_div(d0.d, d1.d, &env->fp_status);
+ update_fpscr(GETPC());
return d0.ll;
}
uint32_t helper_float_FT(uint32_t t0)
{
CPU_FloatU f;
+
+ set_float_exception_flags(0, &env->fp_status);
f.f = int32_to_float32(t0, &env->fp_status);
+ update_fpscr(GETPC());
+
return f.l;
}
uint64_t helper_float_DT(uint32_t t0)
{
CPU_DoubleU d;
+ set_float_exception_flags(0, &env->fp_status);
d.d = int32_to_float64(t0, &env->fp_status);
+ update_fpscr(GETPC());
return d.ll;
}
@@ -590,8 +679,11 @@ uint32_t helper_fmac_FT(uint32_t t0, uint32_t t1, uint32_t t2)
f0.l = t0;
f1.l = t1;
f2.l = t2;
+ set_float_exception_flags(0, &env->fp_status);
f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
f0.f = float32_add(f0.f, f2.f, &env->fp_status);
+ update_fpscr(GETPC());
+
return f0.l;
}
@@ -600,7 +692,9 @@ uint32_t helper_fmul_FT(uint32_t t0, uint32_t t1)
CPU_FloatU f0, f1;
f0.l = t0;
f1.l = t1;
+ set_float_exception_flags(0, &env->fp_status);
f0.f = float32_mul(f0.f, f1.f, &env->fp_status);
+ update_fpscr(GETPC());
return f0.l;
}
@@ -609,7 +703,10 @@ uint64_t helper_fmul_DT(uint64_t t0, uint64_t t1)
CPU_DoubleU d0, d1;
d0.ll = t0;
d1.ll = t1;
+ set_float_exception_flags(0, &env->fp_status);
d0.d = float64_mul(d0.d, d1.d, &env->fp_status);
+ update_fpscr(GETPC());
+
return d0.ll;
}
@@ -625,7 +722,9 @@ uint32_t helper_fsqrt_FT(uint32_t t0)
{
CPU_FloatU f;
f.l = t0;
+ set_float_exception_flags(0, &env->fp_status);
f.f = float32_sqrt(f.f, &env->fp_status);
+ update_fpscr(GETPC());
return f.l;
}
@@ -633,7 +732,9 @@ uint64_t helper_fsqrt_DT(uint64_t t0)
{
CPU_DoubleU d;
d.ll = t0;
+ set_float_exception_flags(0, &env->fp_status);
d.d = float64_sqrt(d.d, &env->fp_status);
+ update_fpscr(GETPC());
return d.ll;
}
@@ -642,29 +743,42 @@ uint32_t helper_fsub_FT(uint32_t t0, uint32_t t1)
CPU_FloatU f0, f1;
f0.l = t0;
f1.l = t1;
+ set_float_exception_flags(0, &env->fp_status);
f0.f = float32_sub(f0.f, f1.f, &env->fp_status);
+ update_fpscr(GETPC());
return f0.l;
}
uint64_t helper_fsub_DT(uint64_t t0, uint64_t t1)
{
CPU_DoubleU d0, d1;
+
d0.ll = t0;
d1.ll = t1;
+ set_float_exception_flags(0, &env->fp_status);
d0.d = float64_sub(d0.d, d1.d, &env->fp_status);
+ update_fpscr(GETPC());
return d0.ll;
}
uint32_t helper_ftrc_FT(uint32_t t0)
{
CPU_FloatU f;
+ uint32_t ret;
f.l = t0;
- return float32_to_int32_round_to_zero(f.f, &env->fp_status);
+ set_float_exception_flags(0, &env->fp_status);
+ ret = float32_to_int32_round_to_zero(f.f, &env->fp_status);
+ update_fpscr(GETPC());
+ return ret;
}
uint32_t helper_ftrc_DT(uint64_t t0)
{
CPU_DoubleU d;
+ uint32_t ret;
d.ll = t0;
- return float64_to_int32_round_to_zero(d.d, &env->fp_status);
+ set_float_exception_flags(0, &env->fp_status);
+ ret = float64_to_int32_round_to_zero(d.d, &env->fp_status);
+ update_fpscr(GETPC());
+ return ret;
}
commit a0d4ac333a8e59152c48ce659dc831391fff6df3
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:18 2011 +0100
target-sh4: implement flush-to-zero
When the FPSCR.DN bit is set, the SH4 FPU treat denormalized numbers as
zero. Enable the corresponding softfloat option when this bit is set.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index d69b94b..9025a29 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -449,6 +449,7 @@ void helper_ld_fpscr(uint32_t val)
} else {
set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
}
+ set_flush_to_zero((val & FPSCR_DN) != 0, &env->fp_status);
}
uint32_t helper_fabs_FT(uint32_t t0)
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index d4cd0a3..8b2f1fc 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -205,6 +205,7 @@ static void cpu_sh4_reset(CPUSH4State * env)
#else
env->fpscr = FPSCR_DN | FPSCR_RM_ZERO; /* CPU reset value according to SH4 manual */
set_float_rounding_mode(float_round_to_zero, &env->fp_status);
+ set_flush_to_zero(1, &env->fp_status);
#endif
set_default_nan_mode(1, &env->fp_status);
env->mmucr = 0;
commit 26ac1ea5590c2710d050bfe2630c1546f109d28c
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:18 2011 +0100
target-sh4: define FPSCR constants
Define FPSCR constants for all field and use them instead of hardcoded
values.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h
index 8ccf25c..fe33b8a 100644
--- a/target-sh4/cpu.h
+++ b/target-sh4/cpu.h
@@ -61,10 +61,37 @@
#define SR_S (1 << 1)
#define SR_T (1 << 0)
-#define FPSCR_FR (1 << 21)
-#define FPSCR_SZ (1 << 20)
-#define FPSCR_PR (1 << 19)
-#define FPSCR_DN (1 << 18)
+#define FPSCR_MASK (0x003fffff)
+#define FPSCR_FR (1 << 21)
+#define FPSCR_SZ (1 << 20)
+#define FPSCR_PR (1 << 19)
+#define FPSCR_DN (1 << 18)
+#define FPSCR_CAUSE_MASK (0x3f << 12)
+#define FPSCR_CAUSE_SHIFT (12)
+#define FPSCR_CAUSE_E (1 << 17)
+#define FPSCR_CAUSE_V (1 << 16)
+#define FPSCR_CAUSE_Z (1 << 15)
+#define FPSCR_CAUSE_O (1 << 14)
+#define FPSCR_CAUSE_U (1 << 13)
+#define FPSCR_CAUSE_I (1 << 12)
+#define FPSCR_ENABLE_MASK (0x1f << 7)
+#define FPSCR_ENABLE_SHIFT (7)
+#define FPSCR_ENABLE_V (1 << 11)
+#define FPSCR_ENABLE_Z (1 << 10)
+#define FPSCR_ENABLE_O (1 << 9)
+#define FPSCR_ENABLE_U (1 << 8)
+#define FPSCR_ENABLE_I (1 << 7)
+#define FPSCR_FLAG_MASK (0x1f << 2)
+#define FPSCR_FLAG_SHIFT (2)
+#define FPSCR_FLAG_V (1 << 6)
+#define FPSCR_FLAG_Z (1 << 5)
+#define FPSCR_FLAG_O (1 << 4)
+#define FPSCR_FLAG_U (1 << 3)
+#define FPSCR_FLAG_I (1 << 2)
+#define FPSCR_RM_MASK (0x03 << 0)
+#define FPSCR_RM_NEAREST (0 << 0)
+#define FPSCR_RM_ZERO (1 << 0)
+
#define DELAY_SLOT (1 << 0)
#define DELAY_SLOT_CONDITIONAL (1 << 1)
#define DELAY_SLOT_TRUE (1 << 2)
diff --git a/target-sh4/op_helper.c b/target-sh4/op_helper.c
index 2e5f555..d69b94b 100644
--- a/target-sh4/op_helper.c
+++ b/target-sh4/op_helper.c
@@ -443,11 +443,12 @@ static inline void clr_t(void)
void helper_ld_fpscr(uint32_t val)
{
- env->fpscr = val & 0x003fffff;
- if (val & 0x01)
+ env->fpscr = val & FPSCR_MASK;
+ if ((val & FPSCR_RM_MASK) == FPSCR_RM_ZERO) {
set_float_rounding_mode(float_round_to_zero, &env->fp_status);
- else
+ } else {
set_float_rounding_mode(float_round_nearest_even, &env->fp_status);
+ }
}
uint32_t helper_fabs_FT(uint32_t t0)
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 1858423..d4cd0a3 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -203,10 +203,10 @@ static void cpu_sh4_reset(CPUSH4State * env)
env->fpscr = FPSCR_PR; /* value for userspace according to the kernel */
set_float_rounding_mode(float_round_nearest_even, &env->fp_status); /* ?! */
#else
- env->fpscr = 0x00040001; /* CPU reset value according to SH4 manual */
+ env->fpscr = FPSCR_DN | FPSCR_RM_ZERO; /* CPU reset value according to SH4 manual */
set_float_rounding_mode(float_round_to_zero, &env->fp_status);
#endif
- set_default_nan_mode(1, &env->vfp.fp_status);
+ set_default_nan_mode(1, &env->fp_status);
env->mmucr = 0;
}
commit 442599a340ad04f2915c471430ae8a93cb42b261
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:17 2011 +0100
target-sh4: use default-NaN mode
SH4 FPU doesn't propagate NaN, and instead always regenerate new ones.
Enable the default-NaN mode by default.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 37915d5..1858423 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -206,6 +206,7 @@ static void cpu_sh4_reset(CPUSH4State * env)
env->fpscr = 0x00040001; /* CPU reset value according to SH4 manual */
set_float_rounding_mode(float_round_to_zero, &env->fp_status);
#endif
+ set_default_nan_mode(1, &env->vfp.fp_status);
env->mmucr = 0;
}
commit 102016020bb0f368958ae91d293e13c61b3923a1
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:17 2011 +0100
softfloat: fix default-NaN mode
When the default-NaN mode is enabled, it should return the default NaN
value, but it should anyway raise the invalid operation flag if one of
the operand is an sNaN.
I have checked that this behavior matches the ARM and SH4 manuals, as
well as real SH4 hardware.
Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 186b4da..11521ce 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -278,9 +278,6 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
flag aIsLargerSignificand;
bits32 av, bv;
- if ( STATUS(default_nan_mode) )
- return float32_default_nan;
-
aIsQuietNaN = float32_is_quiet_nan( a );
aIsSignalingNaN = float32_is_signaling_nan( a );
bIsQuietNaN = float32_is_quiet_nan( b );
@@ -290,6 +287,9 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
+ if ( STATUS(default_nan_mode) )
+ return float32_default_nan;
+
if ((bits32)(av<<1) < (bits32)(bv<<1)) {
aIsLargerSignificand = 0;
} else if ((bits32)(bv<<1) < (bits32)(av<<1)) {
@@ -423,9 +423,6 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
flag aIsLargerSignificand;
bits64 av, bv;
- if ( STATUS(default_nan_mode) )
- return float64_default_nan;
-
aIsQuietNaN = float64_is_quiet_nan( a );
aIsSignalingNaN = float64_is_signaling_nan( a );
bIsQuietNaN = float64_is_quiet_nan( b );
@@ -435,6 +432,9 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
+ if ( STATUS(default_nan_mode) )
+ return float64_default_nan;
+
if ((bits64)(av<<1) < (bits64)(bv<<1)) {
aIsLargerSignificand = 0;
} else if ((bits64)(bv<<1) < (bits64)(av<<1)) {
@@ -574,12 +574,6 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
flag aIsLargerSignificand;
- if ( STATUS(default_nan_mode) ) {
- a.low = floatx80_default_nan_low;
- a.high = floatx80_default_nan_high;
- return a;
- }
-
aIsQuietNaN = floatx80_is_quiet_nan( a );
aIsSignalingNaN = floatx80_is_signaling_nan( a );
bIsQuietNaN = floatx80_is_quiet_nan( b );
@@ -587,6 +581,12 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
+ if ( STATUS(default_nan_mode) ) {
+ a.low = floatx80_default_nan_low;
+ a.high = floatx80_default_nan_high;
+ return a;
+ }
+
if (a.low < b.low) {
aIsLargerSignificand = 0;
} else if (b.low < a.low) {
@@ -719,12 +719,6 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
flag aIsLargerSignificand;
- if ( STATUS(default_nan_mode) ) {
- a.low = float128_default_nan_low;
- a.high = float128_default_nan_high;
- return a;
- }
-
aIsQuietNaN = float128_is_quiet_nan( a );
aIsSignalingNaN = float128_is_signaling_nan( a );
bIsQuietNaN = float128_is_quiet_nan( b );
@@ -732,6 +726,12 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
+ if ( STATUS(default_nan_mode) ) {
+ a.low = float128_default_nan_low;
+ a.high = float128_default_nan_high;
+ return a;
+ }
+
if (lt128(a.high<<1, a.low, b.high<<1, b.low)) {
aIsLargerSignificand = 0;
} else if (lt128(b.high<<1, b.low, a.high<<1, a.low)) {
commit e90877507ea8864e32692cb79da1685f5ada8c78
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:17 2011 +0100
softfloat: SH4 has the sNaN bit set
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index f293f24..186b4da 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -30,7 +30,7 @@ these four paragraphs for those parts of this code that are retained.
=============================================================================*/
-#if defined(TARGET_MIPS)
+#if defined(TARGET_MIPS) || defined(TARGET_SH4)
#define SNAN_BIT_IS_ONE 1
#else
#define SNAN_BIT_IS_ONE 0
@@ -108,7 +108,7 @@ float32 float32_maybe_silence_nan( float32 a_ )
{
if (float32_is_signaling_nan(a_)) {
#if SNAN_BIT_IS_ONE
-# if defined(TARGET_MIPS)
+# if defined(TARGET_MIPS) || defined(TARGET_SH4)
return float32_default_nan;
# else
# error Rules for silencing a signaling NaN are target-specific
@@ -362,7 +362,7 @@ float64 float64_maybe_silence_nan( float64 a_ )
{
if (float64_is_signaling_nan(a_)) {
#if SNAN_BIT_IS_ONE
-# if defined(TARGET_MIPS)
+# if defined(TARGET_MIPS) || defined(TARGET_SH4)
return float64_default_nan;
# else
# error Rules for silencing a signaling NaN are target-specific
@@ -515,7 +515,7 @@ floatx80 floatx80_maybe_silence_nan( floatx80 a )
{
if (floatx80_is_signaling_nan(a)) {
#if SNAN_BIT_IS_ONE
-# if defined(TARGET_MIPS)
+# if defined(TARGET_MIPS) || defined(TARGET_SH4)
a.low = floatx80_default_nan_low;
a.high = floatx80_default_nan_high;
# else
@@ -664,7 +664,7 @@ float128 float128_maybe_silence_nan( float128 a )
{
if (float128_is_signaling_nan(a)) {
#if SNAN_BIT_IS_ONE
-# if defined(TARGET_MIPS)
+# if defined(TARGET_MIPS) || defined(TARGET_SH4)
a.low = float128_default_nan_low;
a.high = float128_default_nan_high;
# else
commit eb8f77761e88a3e281de5e76fc4baa7f34258b82
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:39:17 2011 +0100
target-sh4: switch sh4 to softfloat
We need to be able to catch exceptions correctly and thus enable softfloat
on SH4.
As all machines except i386 and x86_64 are using softfloat, make it the
default and change the case to detect i386 and x86_64. Note that CRIS
doesn't have an FPU, so it can be configured with both softfloat-native
and softfloat.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 54afdda..d68f862 100755
--- a/configure
+++ b/configure
@@ -3061,11 +3061,11 @@ if test ! -z "$gdb_xml_files" ; then
fi
case "$target_arch2" in
- alpha|arm|armeb|m68k|microblaze|mips|mipsel|mipsn32|mipsn32el|mips64|mips64el|ppc|ppc64|ppc64abi32|ppcemb|s390x|sparc|sparc64|sparc32plus)
- echo "CONFIG_SOFTFLOAT=y" >> $config_target_mak
+ i386|x86_64)
+ echo "CONFIG_NOSOFTFLOAT=y" >> $config_target_mak
;;
*)
- echo "CONFIG_NOSOFTFLOAT=y" >> $config_target_mak
+ echo "CONFIG_SOFTFLOAT=y" >> $config_target_mak
;;
esac
commit eae30c8f409ad17d7064a7f0e5c00a80f5f52d35
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jan 14 20:21:22 2011 +0100
configure: fix broken test
Since commit d1807a4f836c27f6dc7061e53a834dd27f78e46a ./configure tries
to test files and directories with "test -f", which only test for regular
files. Test with "test -e", which looks for any kind of files.
This unbreak the configure script when not using a separate object
directory.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index c058934..54afdda 100755
--- a/configure
+++ b/configure
@@ -3241,7 +3241,7 @@ for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.dtb $source_p
done
mkdir -p $DIRS
for f in $FILES ; do
- test -f $f || symlink $source_path/$f $f
+ test -e $f || symlink $source_path/$f $f
done
# temporary config to build submodules
commit 74242e0f7f4bf3d85fe28b939a3d66827fe653e5
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:44:02 2010 +0100
make trace options use autoconfy names
These are not in any release, so I am just renaming them.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index ee782db..c058934 100755
--- a/configure
+++ b/configure
@@ -515,9 +515,9 @@ for opt do
;;
--target-list=*) target_list="$optarg"
;;
- --trace-backend=*) trace_backend="$optarg"
+ --enable-trace-backend=*) trace_backend="$optarg"
;;
- --trace-file=*) trace_file="$optarg"
+ --with-trace-file=*) trace_file="$optarg"
;;
--enable-gprof) gprof="yes"
;;
@@ -907,8 +907,8 @@ echo " --enable-docs enable documentation build"
echo " --disable-docs disable documentation build"
echo " --disable-vhost-net disable vhost-net acceleration support"
echo " --enable-vhost-net enable vhost-net acceleration support"
-echo " --trace-backend=B Trace backend nop simple ust dtrace"
-echo " --trace-file=NAME Full PATH,NAME of file to store traces"
+echo " --enable-trace-backend=B Trace backend nop simple ust dtrace"
+echo " --with-trace-file=NAME Full PATH,NAME of file to store traces"
echo " Default:trace-<pid>"
echo " --disable-spice disable spice"
echo " --enable-spice enable spice"
commit ca4deeb13abc72e3ac5a9e5bc86a25bc2d423b16
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:44:00 2010 +0100
move --srcdir detection earlier
This will help getting config.guess and config.sub from the srcdir.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index 988008a..ee782db 100755
--- a/configure
+++ b/configure
@@ -75,6 +75,7 @@ path_of() {
}
# default parameters
+source_path=`dirname "$0"`
cpu=""
interp_prefix="/usr/gnemul/qemu-%M"
static="no"
@@ -182,6 +183,8 @@ for opt do
;;
--cc=*) CC="$optarg"
;;
+ --source-path=*) source_path="$optarg"
+ ;;
--cpu=*) cpu="$optarg"
;;
--extra-cflags=*) QEMU_CFLAGS="$optarg $QEMU_CFLAGS"
@@ -228,6 +231,9 @@ QEMU_CFLAGS="-D_FORTIFY_SOURCE=2 $QEMU_CFLAGS"
QEMU_INCLUDES="-I. -I\$(SRC_PATH)"
LDFLAGS="-g $LDFLAGS"
+# make source path absolute
+source_path=`cd "$source_path"; pwd`
+
check_define() {
cat > $TMPC <<EOF
#if !defined($1)
@@ -478,10 +484,6 @@ if test "$mingw32" = "yes" ; then
confsuffix=""
fi
-# find source path
-source_path=`dirname "$0"`
-source_path=`cd "$source_path"; pwd`
-
werror=""
for opt do
@@ -493,7 +495,7 @@ for opt do
;;
--interp-prefix=*) interp_prefix="$optarg"
;;
- --source-path=*) source_path="$optarg"
+ --source-path=*)
;;
--cross-prefix=*)
;;
commit ddc0966462ebd05211020b29a5d620bf44ddefaf
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:44:01 2010 +0100
[PATCH v3 14/15] remove HOST_CC mention from roms/{sea, vga}bios/config.mak
Not used in the submodules.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index 6ade985..988008a 100755
--- a/configure
+++ b/configure
@@ -3252,7 +3252,6 @@ for rom in seabios vgabios ; do
echo "CPP=${cross_prefix}cpp" >> $config_mak
echo "OBJCOPY=objcopy" >> $config_mak
echo "IASL=iasl" >> $config_mak
- echo "HOST_CC=$host_cc" >> $config_mak
echo "LD=$ld" >> $config_mak
done
commit d1807a4f836c27f6dc7061e53a834dd27f78e46a
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:43:59 2010 +0100
remove source_path_used
Not necessary since we use mkdir -p and from this patch test -f.
Also, dirname returns "." if a path has no directory component,
as is the case for "sh configure".
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index 5bbf909..6ade985 100755
--- a/configure
+++ b/configure
@@ -480,14 +480,7 @@ fi
# find source path
source_path=`dirname "$0"`
-source_path_used="no"
-workdir=`pwd`
-if [ -z "$source_path" ]; then
- source_path=$workdir
-else
- source_path=`cd "$source_path"; pwd`
-fi
-[ -f "$workdir/vl.c" ] || source_path_used="yes"
+source_path=`cd "$source_path"; pwd`
werror=""
@@ -501,7 +494,6 @@ for opt do
--interp-prefix=*) interp_prefix="$optarg"
;;
--source-path=*) source_path="$optarg"
- source_path_used="yes"
;;
--cross-prefix=*)
;;
@@ -3234,26 +3226,21 @@ echo "QEMU_INCLUDES+=$includes" >> $config_target_mak
done # for target in $targets
-# build tree in object directory if source path is different from current one
-if test "$source_path_used" = "yes" ; then
- DIRS="tests tests/cris slirp audio block net pc-bios/optionrom"
- DIRS="$DIRS roms/seabios roms/vgabios"
- DIRS="$DIRS fsdev ui"
- FILES="Makefile tests/Makefile"
- FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
- FILES="$FILES tests/test-mmap.c"
- FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
- FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
- for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
- FILES="$FILES pc-bios/`basename $bios_file`"
- done
- for dir in $DIRS ; do
- mkdir -p $dir
- done
- for f in $FILES ; do
- symlink $source_path/$f $f
- done
-fi
+# build tree in object directory in case the source is not in the current directory
+DIRS="tests tests/cris slirp audio block net pc-bios/optionrom"
+DIRS="$DIRS roms/seabios roms/vgabios"
+DIRS="$DIRS fsdev ui"
+FILES="Makefile tests/Makefile"
+FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
+FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
+FILES="$FILES roms/seabios/Makefile roms/vgabios/Makefile"
+for bios_file in $source_path/pc-bios/*.bin $source_path/pc-bios/*.dtb $source_path/pc-bios/openbios-*; do
+ FILES="$FILES pc-bios/`basename $bios_file`"
+done
+mkdir -p $DIRS
+for f in $FILES ; do
+ test -f $f || symlink $source_path/$f $f
+done
# temporary config to build submodules
for rom in seabios vgabios ; do
commit 11568d6df9113bb9e7c3d84de6914f335376bd6a
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:43:58 2010 +0100
move "ln -sf" emulation to a function
"ln -sf" does not really do anything more than "ln -s" on Solaris.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index 134863b..5bbf909 100755
--- a/configure
+++ b/configure
@@ -32,6 +32,12 @@ compile_prog() {
$cc $QEMU_CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags >> config.log 2>&1
}
+# symbolically link $1 to $2. Portable version of "ln -sf".
+symlink() {
+ rm -f $2
+ ln -s $1 $2
+}
+
# check whether a command is available to this shell (may be either an
# executable or a builtin)
has() {
@@ -2811,8 +2817,7 @@ fi
for d in libdis libdis-user; do
mkdir -p $d
- rm -f $d/Makefile
- ln -s $source_path/Makefile.dis $d/Makefile
+ symlink $source_path/Makefile.dis $d/Makefile
echo > $d/config.mak
done
if test "$static" = "no" -a "$user_pie" = "yes" ; then
@@ -2876,12 +2881,7 @@ mkdir -p $target_dir/ide
if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" -o "$target" = "arm-bsd-user" -o "$target" = "armeb-bsd-user" ; then
mkdir -p $target_dir/nwfpe
fi
-
-#
-# don't use ln -sf as not all "ln -sf" over write the file/link
-#
-rm -f $target_dir/Makefile
-ln -s $source_path/Makefile.target $target_dir/Makefile
+symlink $source_path/Makefile.target $target_dir/Makefile
echo "# Automatically generated by configure - do not modify" > $config_target_mak
@@ -3250,10 +3250,8 @@ if test "$source_path_used" = "yes" ; then
for dir in $DIRS ; do
mkdir -p $dir
done
- # remove the link and recreate it, as not all "ln -sf" overwrite the link
for f in $FILES ; do
- rm -f $f
- ln -s $source_path/$f $f
+ symlink $source_path/$f $f
done
fi
@@ -3275,15 +3273,13 @@ for hwlib in 32 64; do
d=libhw$hwlib
mkdir -p $d
mkdir -p $d/ide
- rm -f $d/Makefile
- ln -s $source_path/Makefile.hw $d/Makefile
+ symlink $source_path/Makefile.hw $d/Makefile
echo "QEMU_CFLAGS+=-DTARGET_PHYS_ADDR_BITS=$hwlib" > $d/config.mak
done
d=libuser
mkdir -p $d
-rm -f $d/Makefile
-ln -s $source_path/Makefile.user $d/Makefile
+symlink $source_path/Makefile.user $d/Makefile
if test "$static" = "no" -a "$user_pie" = "yes" ; then
echo "QEMU_CFLAGS+=-fpie" > $d/config.mak
fi
commit 3ec87ffe17650c585c52cb3d89d0645ccccd49e1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:43:57 2010 +0100
reorganize sdl-config tests
This also allows overriding it with SDL_CONFIG, and warning in suspicious
cross-compilation scenarios.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index c6e4aa0..134863b 100755
--- a/configure
+++ b/configure
@@ -210,6 +210,7 @@ ld="${cross_prefix}${LD-ld}"
strip="${cross_prefix}${STRIP-strip}"
windres="${cross_prefix}${WINDRES-windres}"
pkg_config="${cross_prefix}${PKG_CONFIG-pkg-config}"
+sdl_config="${cross_prefix}${SDL_CONFIG-sdl-config}"
# default flags for all hosts
QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS"
@@ -1183,21 +1184,17 @@ fi
##########################################
# SDL probe
-# Look for sdl configuration program (pkg-config or sdl-config).
-# Prefer variant with cross prefix if cross compiling,
-# and favour pkg-config with sdl over sdl-config.
-if test -n "$cross_prefix" -a $pkg_config != pkg-config && \
- $pkg_config sdl --modversion >/dev/null 2>&1; then
- sdlconfig="$pkg_config sdl"
- _sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'`
-elif test -n "$cross_prefix" && has ${cross_prefix}sdl-config; then
- sdlconfig="${cross_prefix}sdl-config"
- _sdlversion=`$sdlconfig --version | sed 's/[^0-9]//g'`
-elif $pkg_config sdl --modversion >/dev/null 2>&1; then
+# Look for sdl configuration program (pkg-config or sdl-config). Try
+# sdl-config even without cross prefix, and favour pkg-config over sdl-config.
+if test "`basename $sdl_config`" != sdl-config && ! has ${sdl_config}; then
+ sdl_config=sdl-config
+fi
+
+if $pkg_config sdl --modversion >/dev/null 2>&1; then
sdlconfig="$pkg_config sdl"
_sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'`
-elif has sdl-config; then
- sdlconfig='sdl-config'
+elif has ${sdl_config}; then
+ sdlconfig="$sdl_config"
_sdlversion=`$sdlconfig --version | sed 's/[^0-9]//g'`
else
if test "$sdl" = "yes" ; then
@@ -1205,6 +1202,9 @@ else
fi
sdl=no
fi
+if test -n "$cross_prefix" && test "`basename $sdlconfig`" = sdl-config; then
+ echo warning: using "\"$sdlconfig\"" to detect cross-compiled sdl >&2
+fi
sdl_too_old=no
if test "$sdl" != "no" ; then
commit 0842154128a6763c63ef011cb967219605625f18
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:43:56 2010 +0100
do not default to non-prefixed pkg-config when cross compiling
This can still be requested with PKG_CONFIG=/path/to/pkg-config.
Just do not use it as a default, and print a warning.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index 7eabae4..c6e4aa0 100755
--- a/configure
+++ b/configure
@@ -1163,8 +1163,8 @@ fi
# pkg-config probe
if ! has $pkg_config; then
- # likely not cross compiling, or hope for the best
- pkg_config=pkg-config
+ echo warning: proceeding without "$pkg_config" >&2
+ pkg_config=/bin/false
fi
##########################################
commit a8bd70ad3b62701037e9f3a996762ca7c29581a2
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:43:55 2010 +0100
fix spelling of $pkg_config, move default together with other cross tools
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index 758751e..7eabae4 100755
--- a/configure
+++ b/configure
@@ -209,6 +209,7 @@ objcopy="${cross_prefix}${OBJCOPY-objcopy}"
ld="${cross_prefix}${LD-ld}"
strip="${cross_prefix}${STRIP-strip}"
windres="${cross_prefix}${WINDRES-windres}"
+pkg_config="${cross_prefix}${PKG_CONFIG-pkg-config}"
# default flags for all hosts
QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS"
@@ -1159,12 +1160,11 @@ EOF
fi
##########################################
-# pkgconfig probe
+# pkg-config probe
-pkgconfig="${cross_prefix}pkg-config"
-if ! has $pkgconfig; then
+if ! has $pkg_config; then
# likely not cross compiling, or hope for the best
- pkgconfig=pkg-config
+ pkg_config=pkg-config
fi
##########################################
@@ -1186,15 +1186,15 @@ fi
# Look for sdl configuration program (pkg-config or sdl-config).
# Prefer variant with cross prefix if cross compiling,
# and favour pkg-config with sdl over sdl-config.
-if test -n "$cross_prefix" -a $pkgconfig != pkg-config && \
- $pkgconfig sdl --modversion >/dev/null 2>&1; then
- sdlconfig="$pkgconfig sdl"
+if test -n "$cross_prefix" -a $pkg_config != pkg-config && \
+ $pkg_config sdl --modversion >/dev/null 2>&1; then
+ sdlconfig="$pkg_config sdl"
_sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'`
elif test -n "$cross_prefix" && has ${cross_prefix}sdl-config; then
sdlconfig="${cross_prefix}sdl-config"
_sdlversion=`$sdlconfig --version | sed 's/[^0-9]//g'`
-elif $pkgconfig sdl --modversion >/dev/null 2>&1; then
- sdlconfig="$pkgconfig sdl"
+elif $pkg_config sdl --modversion >/dev/null 2>&1; then
+ sdlconfig="$pkg_config sdl"
_sdlversion=`$sdlconfig --modversion 2>/dev/null | sed 's/[^0-9]//g'`
elif has sdl-config; then
sdlconfig='sdl-config'
@@ -1274,8 +1274,8 @@ if test "$vnc_tls" != "no" ; then
#include <gnutls/gnutls.h>
int main(void) { gnutls_session_t s; gnutls_init(&s, GNUTLS_SERVER); return 0; }
EOF
- vnc_tls_cflags=`$pkgconfig --cflags gnutls 2> /dev/null`
- vnc_tls_libs=`$pkgconfig --libs gnutls 2> /dev/null`
+ vnc_tls_cflags=`$pkg_config --cflags gnutls 2> /dev/null`
+ vnc_tls_libs=`$pkg_config --libs gnutls 2> /dev/null`
if compile_prog "$vnc_tls_cflags" "$vnc_tls_libs" ; then
vnc_tls=yes
libs_softmmu="$vnc_tls_libs $libs_softmmu"
@@ -1589,8 +1589,8 @@ fi
##########################################
# curl probe
-if $pkgconfig libcurl --modversion >/dev/null 2>&1; then
- curlconfig="$pkgconfig libcurl"
+if $pkg_config libcurl --modversion >/dev/null 2>&1; then
+ curlconfig="$pkg_config libcurl"
else
curlconfig=curl-config
fi
@@ -1622,7 +1622,7 @@ if test "$check_utests" != "no" ; then
#include <check.h>
int main(void) { suite_create("qemu test"); return 0; }
EOF
- check_libs=`$pkgconfig --libs check`
+ check_libs=`$pkg_config --libs check`
if compile_prog "" $check_libs ; then
check_utests=yes
libs_tools="$check_libs $libs_tools"
@@ -1641,8 +1641,8 @@ if test "$bluez" != "no" ; then
#include <bluetooth/bluetooth.h>
int main(void) { return bt_error(0); }
EOF
- bluez_cflags=`$pkgconfig --cflags bluez 2> /dev/null`
- bluez_libs=`$pkgconfig --libs bluez 2> /dev/null`
+ bluez_cflags=`$pkg_config --cflags bluez 2> /dev/null`
+ bluez_libs=`$pkg_config --libs bluez 2> /dev/null`
if compile_prog "$bluez_cflags" "$bluez_libs" ; then
bluez=yes
libs_softmmu="$bluez_libs $libs_softmmu"
@@ -1686,7 +1686,7 @@ EOF
kvm_cflags="$kvm_cflags -I$kerneldir/arch/$cpu/include"
fi
else
- kvm_cflags=`$pkgconfig --cflags kvm-kmod 2>/dev/null`
+ kvm_cflags=`$pkg_config --cflags kvm-kmod 2>/dev/null`
fi
if compile_prog "$kvm_cflags" "" ; then
kvm=yes
commit 70be1a2e1ac5ce37e809d220bb4db449633e07b1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:43:54 2010 +0100
provide portable HOST_LONG_BITS test
Do not hardcode the list of 64-bit CPUs. Use sizeof(void *) to
compute it. Renaming it to HOST_LONG_BITS to HOST_POINTER_BITS
is left for later.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index a9ffa22..758751e 100755
--- a/configure
+++ b/configure
@@ -1084,13 +1084,15 @@ esac
fi
-# host long bits test
-hostlongbits="32"
-case "$cpu" in
- x86_64|alpha|ia64|sparc64|ppc64|s390x)
- hostlongbits=64
- ;;
-esac
+# host long bits test, actually a pointer size test
+cat > $TMPC << EOF
+int sizeof_pointer_is_8[sizeof(void *) == 8 ? 1 : -1];
+EOF
+if compile_object; then
+hostlongbits=64
+else
+hostlongbits=32
+fi
##########################################
commit f9728943ff8eec02c17e9eaa34dc8203e0ef8cc2
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:43:53 2010 +0100
do not pass bogus $(SRC_PATH) include paths to cc during configure
Non-existent -I paths are dropped silently by the compiler, but still
it is not polite to pass bogus options. Configure-time tests do not
need any include files from the source path, so only include -I flags
at make time (when they're properly expanded).
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index 113ede6..a9ffa22 100755
--- a/configure
+++ b/configure
@@ -217,7 +217,7 @@ QEMU_CFLAGS="-Wall -Wundef -Wendif-labels -Wwrite-strings -Wmissing-prototypes $
QEMU_CFLAGS="-Wstrict-prototypes -Wredundant-decls $QEMU_CFLAGS"
QEMU_CFLAGS="-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE $QEMU_CFLAGS"
QEMU_CFLAGS="-D_FORTIFY_SOURCE=2 $QEMU_CFLAGS"
-QEMU_CFLAGS="-I. -I\$(SRC_PATH) $QEMU_CFLAGS"
+QEMU_INCLUDES="-I. -I\$(SRC_PATH)"
LDFLAGS="-g $LDFLAGS"
check_define() {
@@ -2545,7 +2545,7 @@ if test $profiler = "yes" ; then
fi
if test "$slirp" = "yes" ; then
echo "CONFIG_SLIRP=y" >> $config_host_mak
- QEMU_CFLAGS="-I\$(SRC_PATH)/slirp $QEMU_CFLAGS"
+ QEMU_INCLUDES="-I\$(SRC_PATH)/slirp $QEMU_INCLUDES"
fi
if test "$vde" = "yes" ; then
echo "CONFIG_VDE=y" >> $config_host_mak
@@ -2781,6 +2781,7 @@ echo "LD=$ld" >> $config_host_mak
echo "WINDRES=$windres" >> $config_host_mak
echo "CFLAGS=$CFLAGS" >> $config_host_mak
echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak
+echo "QEMU_INCLUDES=$QEMU_INCLUDES" >> $config_host_mak
if test "$sparse" = "yes" ; then
echo "CC := REAL_CC=\"\$(CC)\" cgcc" >> $config_host_mak
echo "HOST_CC := REAL_CC=\"\$(HOST_CC)\" cgcc" >> $config_host_mak
@@ -3089,19 +3090,20 @@ fi
# generate QEMU_CFLAGS/LDFLAGS for targets
cflags=""
+includes=""
ldflags=""
if test "$ARCH" = "sparc64" ; then
- cflags="-I\$(SRC_PATH)/tcg/sparc $cflags"
+ includes="-I\$(SRC_PATH)/tcg/sparc $includes"
elif test "$ARCH" = "s390x" ; then
- cflags="-I\$(SRC_PATH)/tcg/s390 $cflags"
+ includes="-I\$(SRC_PATH)/tcg/s390 $includes"
elif test "$ARCH" = "x86_64" ; then
- cflags="-I\$(SRC_PATH)/tcg/i386 $cflags"
+ includes="-I\$(SRC_PATH)/tcg/i386 $includes"
else
- cflags="-I\$(SRC_PATH)/tcg/\$(ARCH) $cflags"
+ includes="-I\$(SRC_PATH)/tcg/\$(ARCH) $includes"
fi
-cflags="-I\$(SRC_PATH)/tcg $cflags"
-cflags="-I\$(SRC_PATH)/fpu $cflags"
+includes="-I\$(SRC_PATH)/tcg $includes"
+includes="-I\$(SRC_PATH)/fpu $includes"
if test "$target_user_only" = "yes" ; then
libdis_config_mak=libdis-user/config.mak
@@ -3226,6 +3228,7 @@ fi
echo "LDFLAGS+=$ldflags" >> $config_target_mak
echo "QEMU_CFLAGS+=$cflags" >> $config_target_mak
+echo "QEMU_INCLUDES+=$includes" >> $config_target_mak
done # for target in $targets
diff --git a/rules.mak b/rules.mak
index 6dac777..738eec3 100644
--- a/rules.mak
+++ b/rules.mak
@@ -15,13 +15,13 @@ MAKEFLAGS += -rR
QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d
%.o: %.c
- $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CC $(TARGET_DIR)$@")
+ $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_INCLUDES) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CC $(TARGET_DIR)$@")
%.o: %.S
- $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," AS $(TARGET_DIR)$@")
+ $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_INCLUDES) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," AS $(TARGET_DIR)$@")
%.o: %.m
- $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@")
+ $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_INCLUDES) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," OBJC $(TARGET_DIR)$@")
LINK = $(call quiet-command,$(CC) $(QEMU_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ $(1) $(LIBS)," LINK $(TARGET_DIR)$@")
diff --git a/tests/Makefile b/tests/Makefile
index e43ec70..9ded4b7 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -7,7 +7,8 @@ QEMU=../i386-linux-user/qemu-i386
QEMU_X86_64=../x86_64-linux-user/qemu-x86_64
CC_X86_64=$(CC_I386) -m64
-CFLAGS=-Wall -O2 -g -fno-strict-aliasing -I..
+QEMU_INCLUDES += -I..
+CFLAGS=-Wall -O2 -g -fno-strict-aliasing
#CFLAGS+=-msse2
LDFLAGS=
commit 8d05095cec5feabba03078d5fabf5ac207fa8d4b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:43:52 2010 +0100
test cc with the complete set of chosen flags
The "test the C compiler works ok" comes before a bunch of flags
are added for --cpu or just depending on the host. It helps
debugging if the test is done after these flags are (unconditionally)
added.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index 11a7b18..113ede6 100755
--- a/configure
+++ b/configure
@@ -220,31 +220,6 @@ QEMU_CFLAGS="-D_FORTIFY_SOURCE=2 $QEMU_CFLAGS"
QEMU_CFLAGS="-I. -I\$(SRC_PATH) $QEMU_CFLAGS"
LDFLAGS="-g $LDFLAGS"
-gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
-gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
-gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
-gcc_flags="-fstack-protector-all $gcc_flags"
-cat > $TMPC << EOF
-int main(void) { return 0; }
-EOF
-for flag in $gcc_flags; do
- if compile_prog "-Werror $QEMU_CFLAGS" "-Werror $flag" ; then
- QEMU_CFLAGS="$QEMU_CFLAGS $flag"
- fi
-done
-
-# check that the C compiler works.
-cat > $TMPC <<EOF
-int main(void) {}
-EOF
-
-if compile_object ; then
- : C compiler works ok
-else
- echo "ERROR: \"$cc\" either does not exist or does not work"
- exit 1
-fi
-
check_define() {
cat > $TMPC <<EOF
#if !defined($1)
@@ -941,6 +916,31 @@ echo "NOTE: The object files are built at the place where configure is launched"
exit 1
fi
+# check that the C compiler works.
+cat > $TMPC <<EOF
+int main(void) {}
+EOF
+
+if compile_object ; then
+ : C compiler works ok
+else
+ echo "ERROR: \"$cc\" either does not exist or does not work"
+ exit 1
+fi
+
+gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
+gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
+gcc_flags="-Wmissing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
+gcc_flags="-fstack-protector-all $gcc_flags"
+cat > $TMPC << EOF
+int main(void) { return 0; }
+EOF
+for flag in $gcc_flags; do
+ if compile_prog "-Werror $QEMU_CFLAGS" "-Werror $flag" ; then
+ QEMU_CFLAGS="$QEMU_CFLAGS $flag"
+ fi
+done
+
#
# Solaris specific configure tool chain decisions
#
commit e39f0062cccaade333bd10fa27f3807f0a76f383
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:43:51 2010 +0100
fix sparse support (?)
I didn't test with sparse, but the old code using += before a variable
was set was wrong. Sparse support should probably be ripped out or
redone, but this at least keeps some sanity.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index 13b2aa7..11a7b18 100755
--- a/configure
+++ b/configure
@@ -2775,17 +2775,17 @@ echo "INSTALL_PROG=$install -m0755 -p" >> $config_host_mak
echo "CC=$cc" >> $config_host_mak
echo "CC_I386=$cc_i386" >> $config_host_mak
echo "HOST_CC=$host_cc" >> $config_host_mak
-if test "$sparse" = "yes" ; then
- echo "CC := REAL_CC=\"\$(CC)\" cgcc" >> $config_host_mak
- echo "HOST_CC := REAL_CC=\"\$(HOST_CC)\" cgcc" >> $config_host_mak
- echo "QEMU_CFLAGS += -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-non-pointer-null" >> $config_host_mak
-fi
echo "AR=$ar" >> $config_host_mak
echo "OBJCOPY=$objcopy" >> $config_host_mak
echo "LD=$ld" >> $config_host_mak
echo "WINDRES=$windres" >> $config_host_mak
echo "CFLAGS=$CFLAGS" >> $config_host_mak
echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak
+if test "$sparse" = "yes" ; then
+ echo "CC := REAL_CC=\"\$(CC)\" cgcc" >> $config_host_mak
+ echo "HOST_CC := REAL_CC=\"\$(HOST_CC)\" cgcc" >> $config_host_mak
+ echo "QEMU_CFLAGS += -Wbitwise -Wno-transparent-union -Wno-old-initializer -Wno-non-pointer-null" >> $config_host_mak
+fi
echo "HELPER_CFLAGS=$helper_cflags" >> $config_host_mak
echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
echo "ARLIBS_BEGIN=$arlibs_begin" >> $config_host_mak
commit 377529c009e3fce480d9c233bb3238b14a950816
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:43:50 2010 +0100
move feature variables to the top
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index 89cfa12..13b2aa7 100755
--- a/configure
+++ b/configure
@@ -86,6 +86,88 @@ audio_pt_int=""
audio_win_int=""
cc_i386=i386-pc-linux-gnu-gcc
+target_list=""
+
+# Default value for a variable defining feature "foo".
+# * foo="no" feature will only be used if --enable-foo arg is given
+# * foo="" feature will be searched for, and if found, will be used
+# unless --disable-foo is given
+# * foo="yes" this value will only be set by --enable-foo flag.
+# feature will searched for,
+# if not found, configure exits with error
+#
+# Always add --enable-foo and --disable-foo command line args.
+# Distributions want to ensure that several features are compiled in, and it
+# is impossible without a --enable-foo that exits if a feature is not found.
+
+bluez=""
+brlapi=""
+curl=""
+curses=""
+docs=""
+fdt=""
+kvm=""
+kvm_para=""
+nptl=""
+sdl=""
+sparse="no"
+uuid=""
+vde=""
+vnc_tls=""
+vnc_sasl=""
+vnc_jpeg=""
+vnc_png=""
+vnc_thread="no"
+xen=""
+linux_aio=""
+attr=""
+vhost_net=""
+xfs=""
+
+gprof="no"
+debug_tcg="no"
+debug_mon="no"
+debug="no"
+strip_opt="yes"
+bigendian="no"
+mingw32="no"
+EXESUF=""
+prefix="/usr/local"
+mandir="\${prefix}/share/man"
+datadir="\${prefix}/share/qemu"
+docdir="\${prefix}/share/doc/qemu"
+bindir="\${prefix}/bin"
+sysconfdir="\${prefix}/etc"
+confsuffix="/qemu"
+slirp="yes"
+fmod_lib=""
+fmod_inc=""
+oss_lib=""
+bsd="no"
+linux="no"
+solaris="no"
+profiler="no"
+cocoa="no"
+softmmu="yes"
+linux_user="no"
+darwin_user="no"
+bsd_user="no"
+guest_base=""
+uname_release=""
+io_thread="no"
+mixemu="no"
+kerneldir=""
+aix="no"
+blobs="yes"
+pkgversion=""
+check_utests="no"
+user_pie="no"
+zero_malloc=""
+trace_backend="nop"
+trace_file="trace"
+spice=""
+rbd=""
+
# parse CC options first
for opt do
optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
@@ -208,7 +290,6 @@ else
cpu=`uname -m`
fi
-target_list=""
case "$cpu" in
alpha|cris|ia64|m68k|microblaze|ppc|ppc64|sparc64)
cpu="$cpu"
@@ -246,87 +327,6 @@ case "$cpu" in
;;
esac
-# Default value for a variable defining feature "foo".
-# * foo="no" feature will only be used if --enable-foo arg is given
-# * foo="" feature will be searched for, and if found, will be used
-# unless --disable-foo is given
-# * foo="yes" this value will only be set by --enable-foo flag.
-# feature will searched for,
-# if not found, configure exits with error
-#
-# Always add --enable-foo and --disable-foo command line args.
-# Distributions want to ensure that several features are compiled in, and it
-# is impossible without a --enable-foo that exits if a feature is not found.
-
-bluez=""
-brlapi=""
-curl=""
-curses=""
-docs=""
-fdt=""
-kvm=""
-kvm_para=""
-nptl=""
-sdl=""
-sparse="no"
-uuid=""
-vde=""
-vnc_tls=""
-vnc_sasl=""
-vnc_jpeg=""
-vnc_png=""
-vnc_thread="no"
-xen=""
-linux_aio=""
-attr=""
-vhost_net=""
-xfs=""
-
-gprof="no"
-debug_tcg="no"
-debug_mon="no"
-debug="no"
-strip_opt="yes"
-bigendian="no"
-mingw32="no"
-EXESUF=""
-prefix="/usr/local"
-mandir="\${prefix}/share/man"
-datadir="\${prefix}/share/qemu"
-docdir="\${prefix}/share/doc/qemu"
-bindir="\${prefix}/bin"
-sysconfdir="\${prefix}/etc"
-confsuffix="/qemu"
-slirp="yes"
-fmod_lib=""
-fmod_inc=""
-oss_lib=""
-bsd="no"
-linux="no"
-solaris="no"
-profiler="no"
-cocoa="no"
-softmmu="yes"
-linux_user="no"
-darwin_user="no"
-bsd_user="no"
-guest_base=""
-uname_release=""
-io_thread="no"
-mixemu="no"
-kerneldir=""
-aix="no"
-haiku="no"
-blobs="yes"
-pkgversion=""
-check_utests="no"
-user_pie="no"
-zero_malloc=""
-trace_backend="nop"
-trace_file="trace"
-spice=""
-rbd=""
-
# OS specific
if check_define __linux__ ; then
targetos="Linux"
commit 0db4a067594b506678cdaece6c32e870d391695e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:43:49 2010 +0100
default make and install to environment variables
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index fa68359..89cfa12 100755
--- a/configure
+++ b/configure
@@ -79,8 +79,6 @@ audio_card_list="ac97 es1370 sb16 hda"
audio_possible_cards="ac97 es1370 sb16 cs4231a adlib gus hda"
block_drv_whitelist=""
host_cc="gcc"
-make="make"
-install="install"
helper_cflags=""
libs_softmmu=""
libs_tools=""
@@ -363,7 +361,7 @@ GNU/kFreeBSD)
;;
FreeBSD)
bsd="yes"
- make="gmake"
+ make="${MAKE-gmake}"
audio_drv_list="oss"
audio_possible_drivers="oss sdl esd pa"
# needed for kinfo_getvmmap(3) in libutil.h
@@ -371,20 +369,20 @@ FreeBSD)
;;
DragonFly)
bsd="yes"
- make="gmake"
+ make="${MAKE-gmake}"
audio_drv_list="oss"
audio_possible_drivers="oss sdl esd pa"
;;
NetBSD)
bsd="yes"
- make="gmake"
+ make="${MAKE-gmake}"
audio_drv_list="oss"
audio_possible_drivers="oss sdl esd"
oss_lib="-lossaudio"
;;
OpenBSD)
bsd="yes"
- make="gmake"
+ make="${MAKE-gmake}"
audio_drv_list="oss"
audio_possible_drivers="oss sdl esd"
oss_lib="-lossaudio"
@@ -413,8 +411,8 @@ Darwin)
;;
SunOS)
solaris="yes"
- make="gmake"
- install="ginstall"
+ make="${MAKE-gmake}"
+ install="${INSTALL-ginstall}"
ld="gld"
needs_libsunmath="no"
solarisrev=`uname -r | cut -f2 -d.`
@@ -453,7 +451,7 @@ SunOS)
;;
AIX)
aix="yes"
- make="gmake"
+ make="${MAKE-gmake}"
;;
Haiku)
haiku="yes"
@@ -479,6 +477,9 @@ if [ "$bsd" = "yes" ] ; then
bsd_user="yes"
fi
+: ${make=${MAKE-make}}
+: ${install=${INSTALL-install}}
+
if test "$mingw32" = "yes" ; then
EXESUF=".exe"
QEMU_CFLAGS="-DWIN32_LEAN_AND_MEAN -DWINVER=0x501 $QEMU_CFLAGS"
commit 3d8df6409bdbd6c2f6df44c136ebb24d1248f408
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 11:43:48 2010 +0100
default compilation tools to environment variables
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index 438219b..fa68359 100755
--- a/configure
+++ b/configure
@@ -74,19 +74,13 @@ interp_prefix="/usr/gnemul/qemu-%M"
static="no"
sparc_cpu=""
cross_prefix=""
-cc="gcc"
audio_drv_list=""
audio_card_list="ac97 es1370 sb16 hda"
audio_possible_cards="ac97 es1370 sb16 cs4231a adlib gus hda"
block_drv_whitelist=""
host_cc="gcc"
-ar="ar"
make="make"
install="install"
-objcopy="objcopy"
-ld="ld"
-strip="strip"
-windres="windres"
helper_cflags=""
libs_softmmu=""
libs_tools=""
@@ -100,7 +94,7 @@ for opt do
case "$opt" in
--cross-prefix=*) cross_prefix="$optarg"
;;
- --cc=*) cc="$optarg"
+ --cc=*) CC="$optarg"
;;
--cpu=*) cpu="$optarg"
;;
@@ -129,12 +123,12 @@ done
# Using uname is really, really broken. Once we have the right set of checks
# we can eliminate it's usage altogether
-cc="${cross_prefix}${cc}"
-ar="${cross_prefix}${ar}"
-objcopy="${cross_prefix}${objcopy}"
-ld="${cross_prefix}${ld}"
-strip="${cross_prefix}${strip}"
-windres="${cross_prefix}${windres}"
+cc="${cross_prefix}${CC-gcc}"
+ar="${cross_prefix}${AR-ar}"
+objcopy="${cross_prefix}${OBJCOPY-objcopy}"
+ld="${cross_prefix}${LD-ld}"
+strip="${cross_prefix}${STRIP-strip}"
+windres="${cross_prefix}${WINDRES-windres}"
# default flags for all hosts
QEMU_CFLAGS="-fno-strict-aliasing $QEMU_CFLAGS"
commit 844bab604b4369f6ee84065756da0b1d7f915715
Author: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
Date: Fri Jan 14 12:30:26 2011 +0100
microblaze: Improve unconditional direct branching
Avoid emitting conditional tcg operations for uncoditional
direct branches.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index c018c99..2e236fb 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -78,9 +78,10 @@ typedef struct DisasContext {
unsigned int clear_imm;
int is_jmp;
-#define JMP_NOJMP 0
-#define JMP_DIRECT 1
-#define JMP_INDIRECT 2
+#define JMP_NOJMP 0
+#define JMP_DIRECT 1
+#define JMP_DIRECT_CC 2
+#define JMP_INDIRECT 3
unsigned int jmp;
uint32_t jmp_pc;
@@ -751,7 +752,10 @@ static void dec_bit(DisasContext *dc)
static inline void sync_jmpstate(DisasContext *dc)
{
- if (dc->jmp == JMP_DIRECT) {
+ if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
+ if (dc->jmp == JMP_DIRECT) {
+ tcg_gen_movi_tl(env_btaken, 1);
+ }
dc->jmp = JMP_INDIRECT;
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
}
@@ -975,7 +979,7 @@ static void dec_bcc(DisasContext *dc)
int32_t offset = (int32_t)((int16_t)dc->imm); /* sign-extend. */
tcg_gen_movi_tl(env_btarget, dc->pc + offset);
- dc->jmp = JMP_DIRECT;
+ dc->jmp = JMP_DIRECT_CC;
dc->jmp_pc = dc->pc + offset;
} else {
dc->jmp = JMP_INDIRECT;
@@ -1029,7 +1033,6 @@ static void dec_br(DisasContext *dc)
if (dec_alu_op_b_is_small_imm(dc)) {
dc->jmp = JMP_DIRECT;
dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
- tcg_gen_movi_tl(env_btaken, 1);
} else {
tcg_gen_movi_tl(env_btaken, 1);
tcg_gen_movi_tl(env_btarget, dc->pc);
@@ -1451,6 +1454,10 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
dc->is_jmp = DISAS_JUMP;
} else if (dc->jmp == JMP_DIRECT) {
+ t_sync_flags(dc);
+ gen_goto_tb(dc, 0, dc->jmp_pc);
+ dc->is_jmp = DISAS_TB_JUMP;
+ } else if (dc->jmp == JMP_DIRECT_CC) {
int l1;
t_sync_flags(dc);
@@ -1475,7 +1482,7 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
&& num_insns < max_insns);
npc = dc->pc;
- if (dc->jmp == JMP_DIRECT) {
+ if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
if (dc->tb_flags & D_FLAG) {
dc->is_jmp = DISAS_UPDATE;
tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
commit d03d11260ee2d55579e8b76116e35ccdf5031833
Author: Edgar E. Iglesias <edgar at axis.com>
Date: Thu Jan 13 15:14:04 2011 +0100
cris: Set btaken when storing direct jumps
When storing a direct jmp from translation state into
runtime state we should set the btaken flag.
Signed-off-by: Edgar E. Iglesias <edgar at axis.com>
diff --git a/target-cris/translate.c b/target-cris/translate.c
index e09aaa9..f4cc125 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -1129,6 +1129,9 @@ static void cris_store_direct_jmp(DisasContext *dc)
{
/* Store the direct jmp state into the cpu-state. */
if (dc->jmp == JMP_DIRECT || dc->jmp == JMP_DIRECT_CC) {
+ if (dc->jmp == JMP_DIRECT) {
+ tcg_gen_movi_tl(env_btaken, 1);
+ }
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
dc->jmp = JMP_INDIRECT;
}
commit facf1a60f29853590073f321e3cba491a5ee097a
Author: Sergei Gavrikov <sergei.gavrikov at gmail.com>
Date: Wed Jan 12 15:57:18 2011 +0200
slirp: Use strcasecmp() to check tftp mode, tsize
According to RFC 1350 (TFTP Revision 2) the mode field can contain any
combination of upper and lower case; also RFC 2349 propagates that the
transfer size option ("tsize") is case in-sensitive too.
Current implementation of embedded TFTP server missed that what does
mess some TFTP clients. Fixed by using STRCASECMP(3) in the required
places.
Signed-off-by: Sergei Gavrikov <sergei.gavrikov at gmail.com>
Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Signed-off-by: Edgar E. Iglesias <edgar at axis.com>
diff --git a/slirp/tftp.c b/slirp/tftp.c
index 55e4692..1821648 100644
--- a/slirp/tftp.c
+++ b/slirp/tftp.c
@@ -311,7 +311,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
return;
}
- if (memcmp(&tp->x.tp_buf[k], "octet\0", 6) != 0) {
+ if (strcasecmp((const char *)&tp->x.tp_buf[k], "octet") != 0) {
tftp_send_error(spt, 4, "Unsupported transfer mode", tp);
return;
}
@@ -351,7 +351,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
value = (const char *)&tp->x.tp_buf[k];
k += strlen(value) + 1;
- if (strcmp(key, "tsize") == 0) {
+ if (strcasecmp(key, "tsize") == 0) {
int tsize = atoi(value);
struct stat stat_p;
commit 4508d81a788f451c83604e1d0033243e191d71a7
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Wed Jan 12 21:12:31 2011 +0000
ppc405_uc: fix a buffer overflow
Fix a buffer overflow, reported by cppcheck:
[/src/qemu/hw/ppc405_uc.c:72]: (error) Buffer access out-of-bounds: bd.bi_s_version
The use of field bi_s_version seems to be a typo, it should be
bi_r_version.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 8136cb9..334187e 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -68,8 +68,9 @@ ram_addr_t ppc405_set_bootinfo (CPUState *env, ppc4xx_bd_info_t *bd,
stl_phys(bdloc + 0x34, bd->bi_baudrate);
for (i = 0; i < 4; i++)
stb_phys(bdloc + 0x38 + i, bd->bi_s_version[i]);
- for (i = 0; i < 32; i++)
- stb_phys(bdloc + 0x3C + i, bd->bi_s_version[i]);
+ for (i = 0; i < 32; i++) {
+ stb_phys(bdloc + 0x3C + i, bd->bi_r_version[i]);
+ }
stl_phys(bdloc + 0x5C, bd->bi_plb_busfreq);
stl_phys(bdloc + 0x60, bd->bi_pci_busfreq);
for (i = 0; i < 6; i++)
commit c46a3ea025b147d58e4c7a222307ccba1e9e376f
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Wed Jan 12 21:00:01 2011 +0000
lan9118: fix a buffer overflow
Fix a buffer overflow, reported by cppcheck:
[/src/qemu/hw/lan9118.c:849]: (error) Buffer access out-of-bounds: s.eeprom
All eeprom handling code assumes that the size of eeprom is 128,
except lan9118_eeprom_cmd. Fix this by restricting the address passed.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/lan9118.c b/hw/lan9118.c
index a988664..9cc7952 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -187,7 +187,7 @@ typedef struct {
uint32_t phy_int_mask;
int eeprom_writable;
- uint8_t eeprom[8];
+ uint8_t eeprom[128];
int tx_fifo_size;
LAN9118Packet *txp;
@@ -1003,7 +1003,7 @@ static void lan9118_writel(void *opaque, target_phys_addr_t offset,
s->afc_cfg = val & 0x00ffffff;
break;
case CSR_E2P_CMD:
- lan9118_eeprom_cmd(s, (val >> 28) & 7, val & 0xff);
+ lan9118_eeprom_cmd(s, (val >> 28) & 7, val & 0x7f);
break;
case CSR_E2P_DATA:
s->e2p_data = val & 0xff;
commit f0ff243a16362b82e4dae7bd991d13ba25bb5b2f
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Wed Jan 12 19:49:00 2011 +0000
vpc: fix a file descriptor leak
Fix a file descriptor leak, reported by cppcheck:
[/src/qemu/block/vpc.c:524]: (error) Resource leak: fd
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/block/vpc.c b/block/vpc.c
index 21e2a68..7b025be 100644
--- a/block/vpc.c
+++ b/block/vpc.c
@@ -502,6 +502,7 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
uint8_t secs_per_cyl = 0;
size_t block_size, num_bat_entries;
int64_t total_sectors = 0;
+ int ret = -EIO;
// Read out options
while (options && options->name) {
@@ -521,7 +522,8 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
for (i = 0; total_sectors > (int64_t)cyls * heads * secs_per_cyl; i++) {
if (calculate_geometry(total_sectors + i,
&cyls, &heads, &secs_per_cyl)) {
- return -EFBIG;
+ ret = -EFBIG;
+ goto fail;
}
}
total_sectors = (int64_t) cyls * heads * secs_per_cyl;
@@ -560,22 +562,28 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
block_size = 0x200000;
num_bat_entries = (total_sectors + block_size / 512) / (block_size / 512);
- if (write(fd, buf, HEADER_SIZE) != HEADER_SIZE)
- return -EIO;
+ if (write(fd, buf, HEADER_SIZE) != HEADER_SIZE) {
+ goto fail;
+ }
- if (lseek(fd, 1536 + ((num_bat_entries * 4 + 511) & ~511), SEEK_SET) < 0)
- return -EIO;
- if (write(fd, buf, HEADER_SIZE) != HEADER_SIZE)
- return -EIO;
+ if (lseek(fd, 1536 + ((num_bat_entries * 4 + 511) & ~511), SEEK_SET) < 0) {
+ goto fail;
+ }
+ if (write(fd, buf, HEADER_SIZE) != HEADER_SIZE) {
+ goto fail;
+ }
// Write the initial BAT
- if (lseek(fd, 3 * 512, SEEK_SET) < 0)
- return -EIO;
+ if (lseek(fd, 3 * 512, SEEK_SET) < 0) {
+ goto fail;
+ }
memset(buf, 0xFF, 512);
- for (i = 0; i < (num_bat_entries * 4 + 511) / 512; i++)
- if (write(fd, buf, 512) != 512)
- return -EIO;
+ for (i = 0; i < (num_bat_entries * 4 + 511) / 512; i++) {
+ if (write(fd, buf, 512) != 512) {
+ goto fail;
+ }
+ }
// Prepare the Dynamic Disk Header
@@ -592,13 +600,18 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
dyndisk_header->checksum = be32_to_cpu(vpc_checksum(buf, 1024));
// Write the header
- if (lseek(fd, 512, SEEK_SET) < 0)
- return -EIO;
- if (write(fd, buf, 1024) != 1024)
- return -EIO;
+ if (lseek(fd, 512, SEEK_SET) < 0) {
+ goto fail;
+ }
+ if (write(fd, buf, 1024) != 1024) {
+ goto fail;
+ }
+ ret = 0;
+
+ fail:
close(fd);
- return 0;
+ return ret;
}
static void vpc_close(BlockDriverState *bs)
commit 1afec9138f848cfba517bd2d80167b27216b9df9
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Wed Jan 12 19:48:59 2011 +0000
qemu-io: fix a memory leak
Fix a memory leak, reported by cppcheck:
[/src/qemu/qemu-io.c:1135]: (error) Memory leak: ctx
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/qemu-io.c b/qemu-io.c
index 65dee13..5b24c5e 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1131,8 +1131,10 @@ aio_read_f(int argc, char **argv)
case 'P':
ctx->Pflag = 1;
ctx->pattern = parse_pattern(optarg);
- if (ctx->pattern < 0)
+ if (ctx->pattern < 0) {
+ free(ctx);
return 0;
+ }
break;
case 'q':
ctx->qflag = 1;
commit 08089edcd25b2105a7599309afd0225e839debc6
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Wed Jan 12 19:48:58 2011 +0000
vvfat: fix a file descriptor leak
Fix a file descriptor leak, reported by cppcheck:
[/src/qemu/block/vvfat.c:759]: (error) Resource leak: dir
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/block/vvfat.c b/block/vvfat.c
index 26dd474..fe568fe 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -756,6 +756,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
if (st.st_size > 0x7fffffff) {
fprintf(stderr, "File %s is larger than 2GB\n", buffer);
free(buffer);
+ closedir(dir);
return -2;
}
direntry->size=cpu_to_le32(S_ISDIR(st.st_mode)?0:st.st_size);
commit cedf9a6f4549900f857954059284a96814e4c7a3
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Wed Jan 12 19:48:57 2011 +0000
loader: fix a file descriptor leak
Fix a file descriptor leak, reported by cppcheck:
[/src/qemu/hw/loader.c:311]: (error) Resource leak: fd
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/loader.c b/hw/loader.c
index eb198f6..35d792e 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -307,8 +307,9 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
target_data_order = ELFDATA2LSB;
}
- if (target_data_order != e_ident[EI_DATA])
- return -1;
+ if (target_data_order != e_ident[EI_DATA]) {
+ goto fail;
+ }
lseek(fd, 0, SEEK_SET);
if (e_ident[EI_CLASS] == ELFCLASS64) {
commit 8ce7d35273352ebe19c871e6b32a52db77fa08c3
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Wed Jan 12 19:48:56 2011 +0000
vnc-auth-sasl: fix a memory leak
Fix a memory leak reported by cppcheck:
[/src/qemu/ui/vnc-auth-sasl.c:448]: (error) Memory leak: mechname
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c
index a51ddc8..17a621a 100644
--- a/ui/vnc-auth-sasl.c
+++ b/ui/vnc-auth-sasl.c
@@ -444,22 +444,19 @@ static int protocol_client_auth_sasl_mechname(VncState *vs, uint8_t *data, size_
if (vs->sasl.mechlist[len] != '\0' &&
vs->sasl.mechlist[len] != ',') {
VNC_DEBUG("One %d", vs->sasl.mechlist[len]);
- vnc_client_error(vs);
- return -1;
+ goto fail;
}
} else {
char *offset = strstr(vs->sasl.mechlist, mechname);
VNC_DEBUG("Two %p\n", offset);
if (!offset) {
- vnc_client_error(vs);
- return -1;
+ goto fail;
}
VNC_DEBUG("Two '%s'\n", offset);
if (offset[-1] != ',' ||
(offset[len] != '\0'&&
offset[len] != ',')) {
- vnc_client_error(vs);
- return -1;
+ goto fail;
}
}
@@ -469,6 +466,11 @@ static int protocol_client_auth_sasl_mechname(VncState *vs, uint8_t *data, size_
VNC_DEBUG("Validated mechname '%s'\n", mechname);
vnc_read_when(vs, protocol_client_auth_sasl_start_len, 4);
return 0;
+
+ fail:
+ vnc_client_error(vs);
+ free(mechname);
+ return -1;
}
static int protocol_client_auth_sasl_mechname_len(VncState *vs, uint8_t *data, size_t len)
commit a01a9cb821a29852abb142ec52b26c8488ced6e8
Author: Amit Shah <amit.shah at redhat.com>
Date: Tue Nov 23 17:01:15 2010 +0530
virtio-serial-bus: bump up control vq size to 32
The current default of 16 buffers for the control vq is too small. We
can get more entries in there, for example when asking the guest to add
max. allowed ports.
Note: a more robust solution would involve some kind of event queueing
in host to guarantee no event loss. Added a TODO to look into
this later.
Signed-off-by: Amit Shah <amit.shah at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 74ba5ec..b728040 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -769,10 +769,16 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
/* Add a queue for guest to host transfers for port 0 (backward compat) */
vser->ovqs[0] = virtio_add_queue(vdev, 128, handle_output);
+ /* TODO: host to guest notifications can get dropped
+ * if the queue fills up. Implement queueing in host,
+ * this might also make it possible to reduce the control
+ * queue size: as guest preposts buffers there,
+ * this will save 4Kbyte of guest memory per entry. */
+
/* control queue: host to guest */
- vser->c_ivq = virtio_add_queue(vdev, 16, control_in);
+ vser->c_ivq = virtio_add_queue(vdev, 32, control_in);
/* control queue: guest to host */
- vser->c_ovq = virtio_add_queue(vdev, 16, control_out);
+ vser->c_ovq = virtio_add_queue(vdev, 32, control_out);
for (i = 1; i < vser->bus->max_nr_ports; i++) {
/* Add a per-port queue for host to guest transfers */
commit c2e08bddcd1fa32415c0ee5aa6d3c88a258db4c0
Merge: b36e391... 05bf441...
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Wed Jan 12 17:39:36 2011 +0200
Merge remote branch 'origin/master' into pci
commit 00e076795f2d6dfa0c078ff5d5ee5d77190cb4b9
Author: Michael Walle <michael at walle.cc>
Date: Wed Jan 5 01:05:47 2011 +0100
audio: split sample conversion and volume mixing
Refactor the volume mixing, so it can be reused for capturing devices.
Additionally, it removes superfluous multiplications with the nominal
volume within the hardware voice code path.
Signed-off-by: Michael Walle <michael at walle.cc>
Signed-off-by: malc <av1474 at comtv.ru>
diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 727b9f8..4d72014 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -1097,7 +1097,7 @@ static int alsa_run_in (HWVoiceIn *hw)
}
}
- hw->conv (dst, src, nread, &nominal_volume);
+ hw->conv (dst, src, nread);
src = advance (src, nread << hwshift);
dst += nread;
diff --git a/audio/audio.c b/audio/audio.c
index 1707446..1729c0b 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -104,7 +104,7 @@ static struct {
static AudioState glob_audio_state;
-struct mixeng_volume nominal_volume = {
+const struct mixeng_volume nominal_volume = {
.mute = 0,
#ifdef FLOAT_MIXENG
.r = 1.0,
@@ -702,13 +702,11 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
/*
* Capture
*/
-static void noop_conv (struct st_sample *dst, const void *src,
- int samples, struct mixeng_volume *vol)
+static void noop_conv (struct st_sample *dst, const void *src, int samples)
{
(void) src;
(void) dst;
(void) samples;
- (void) vol;
}
static CaptureVoiceOut *audio_pcm_capture_find_specific (
@@ -956,6 +954,8 @@ int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size)
total += isamp;
}
+ mixeng_volume (sw->buf, ret, &sw->vol);
+
sw->clip (buf, sw->buf, ret);
sw->total_hw_samples_acquired += total;
return ret << sw->info.shift;
@@ -1037,7 +1037,8 @@ int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size)
swlim = ((int64_t) dead << 32) / sw->ratio;
swlim = audio_MIN (swlim, samples);
if (swlim) {
- sw->conv (sw->buf, buf, swlim, &sw->vol);
+ sw->conv (sw->buf, buf, swlim);
+ mixeng_volume (sw->buf, swlim, &sw->vol);
}
while (swlim) {
diff --git a/audio/audio_int.h b/audio/audio_int.h
index d66f2c3..2003f8b 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -211,7 +211,7 @@ extern struct audio_driver esd_audio_driver;
extern struct audio_driver pa_audio_driver;
extern struct audio_driver spice_audio_driver;
extern struct audio_driver winwave_audio_driver;
-extern struct mixeng_volume nominal_volume;
+extern const struct mixeng_volume nominal_volume;
void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as);
void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len);
diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c
index e547955..e2d89fd 100644
--- a/audio/dsoundaudio.c
+++ b/audio/dsoundaudio.c
@@ -831,11 +831,11 @@ static int dsound_run_in (HWVoiceIn *hw)
decr = len1 + len2;
if (p1 && len1) {
- hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume);
+ hw->conv (hw->conv_buf + hw->wpos, p1, len1);
}
if (p2 && len2) {
- hw->conv (hw->conv_buf, p2, len2, &nominal_volume);
+ hw->conv (hw->conv_buf, p2, len2);
}
dsound_unlock_in (dscb, p1, p2, blen1, blen2);
diff --git a/audio/esdaudio.c b/audio/esdaudio.c
index 9a1f2f8..ff97b39 100644
--- a/audio/esdaudio.c
+++ b/audio/esdaudio.c
@@ -346,8 +346,7 @@ static void *qesd_thread_in (void *arg)
break;
}
- hw->conv (hw->conv_buf + wpos, buf, nread >> hw->info.shift,
- &nominal_volume);
+ hw->conv (hw->conv_buf + wpos, buf, nread >> hw->info.shift);
wpos = (wpos + chunk) % hw->samples;
to_grab -= chunk;
}
diff --git a/audio/fmodaudio.c b/audio/fmodaudio.c
index 7f08e14..c34cf53 100644
--- a/audio/fmodaudio.c
+++ b/audio/fmodaudio.c
@@ -488,10 +488,10 @@ static int fmod_run_in (HWVoiceIn *hw)
decr = len1 + len2;
if (p1 && blen1) {
- hw->conv (hw->conv_buf + hw->wpos, p1, len1, &nominal_volume);
+ hw->conv (hw->conv_buf + hw->wpos, p1, len1);
}
if (p2 && len2) {
- hw->conv (hw->conv_buf, p2, len2, &nominal_volume);
+ hw->conv (hw->conv_buf, p2, len2);
}
fmod_unlock_sample (fmd->fmod_sample, p1, p2, blen1, blen2);
diff --git a/audio/mixeng.c b/audio/mixeng.c
index 9f1d93f..4a9e8eb 100644
--- a/audio/mixeng.c
+++ b/audio/mixeng.c
@@ -333,3 +333,28 @@ void mixeng_clear (struct st_sample *buf, int len)
{
memset (buf, 0, len * sizeof (struct st_sample));
}
+
+void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol)
+{
+#ifdef CONFIG_MIXEMU
+ if (vol->mute) {
+ mixeng_clear (buf, len);
+ return;
+ }
+
+ while (len--) {
+#ifdef FLOAT_MIXENG
+ buf->l = buf->l * vol->l;
+ buf->r = buf->r * vol->r;
+#else
+ buf->l = (buf->l * vol->l) >> 32;
+ buf->r = (buf->r * vol->r) >> 32;
+#endif
+ buf += 1;
+ }
+#else
+ (void) buf;
+ (void) len;
+ (void) vol;
+#endif
+}
diff --git a/audio/mixeng.h b/audio/mixeng.h
index 4af1dd9..9de443b 100644
--- a/audio/mixeng.h
+++ b/audio/mixeng.h
@@ -33,8 +33,7 @@ struct mixeng_volume { int mute; int64_t r; int64_t l; };
struct st_sample { int64_t l; int64_t r; };
#endif
-typedef void (t_sample) (struct st_sample *dst, const void *src,
- int samples, struct mixeng_volume *vol);
+typedef void (t_sample) (struct st_sample *dst, const void *src, int samples);
typedef void (f_sample) (void *dst, const struct st_sample *src, int samples);
extern t_sample *mixeng_conv[2][2][2][3];
@@ -47,5 +46,6 @@ void st_rate_flow_mix (void *opaque, struct st_sample *ibuf, struct st_sample *o
int *isamp, int *osamp);
void st_rate_stop (void *opaque);
void mixeng_clear (struct st_sample *buf, int len);
+void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol);
#endif /* mixeng.h */
diff --git a/audio/mixeng_template.h b/audio/mixeng_template.h
index 5617705..a2d0ef8 100644
--- a/audio/mixeng_template.h
+++ b/audio/mixeng_template.h
@@ -31,16 +31,6 @@
#define HALF (IN_MAX >> 1)
#endif
-#ifdef CONFIG_MIXEMU
-#ifdef FLOAT_MIXENG
-#define VOL(a, b) ((a) * (b))
-#else
-#define VOL(a, b) ((a) * (b)) >> 32
-#endif
-#else
-#define VOL(a, b) a
-#endif
-
#define ET glue (ENDIAN_CONVERSION, glue (_, IN_T))
#ifdef FLOAT_MIXENG
@@ -109,40 +99,26 @@ static inline IN_T glue (clip_, ET) (int64_t v)
#endif
static void glue (glue (conv_, ET), _to_stereo)
- (struct st_sample *dst, const void *src, int samples, struct mixeng_volume *vol)
+ (struct st_sample *dst, const void *src, int samples)
{
struct st_sample *out = dst;
IN_T *in = (IN_T *) src;
-#ifdef CONFIG_MIXEMU
- if (vol->mute) {
- mixeng_clear (dst, samples);
- return;
- }
-#else
- (void) vol;
-#endif
+
while (samples--) {
- out->l = VOL (glue (conv_, ET) (*in++), vol->l);
- out->r = VOL (glue (conv_, ET) (*in++), vol->r);
+ out->l = glue (conv_, ET) (*in++);
+ out->r = glue (conv_, ET) (*in++);
out += 1;
}
}
static void glue (glue (conv_, ET), _to_mono)
- (struct st_sample *dst, const void *src, int samples, struct mixeng_volume *vol)
+ (struct st_sample *dst, const void *src, int samples)
{
struct st_sample *out = dst;
IN_T *in = (IN_T *) src;
-#ifdef CONFIG_MIXEMU
- if (vol->mute) {
- mixeng_clear (dst, samples);
- return;
- }
-#else
- (void) vol;
-#endif
+
while (samples--) {
- out->l = VOL (glue (conv_, ET) (in[0]), vol->l);
+ out->l = glue (conv_, ET) (in[0]);
out->r = out->l;
out += 1;
in += 1;
@@ -174,4 +150,3 @@ static void glue (glue (clip_, ET), _from_mono)
#undef ET
#undef HALF
-#undef VOL
diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index d7a55e5..b49e102 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -788,8 +788,7 @@ static int oss_run_in (HWVoiceIn *hw)
hw->info.align + 1);
}
read_samples += nread >> hwshift;
- hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift,
- &nominal_volume);
+ hw->conv (hw->conv_buf + bufs[i].add, p, nread >> hwshift);
}
if (bufs[i].len - nread) {
diff --git a/audio/paaudio.c b/audio/paaudio.c
index ff71dac..9cf685d 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -195,7 +195,7 @@ static void *qpa_thread_in (void *arg)
return NULL;
}
- hw->conv (hw->conv_buf + wpos, buf, chunk, &nominal_volume);
+ hw->conv (hw->conv_buf + wpos, buf, chunk);
wpos = (wpos + chunk) % hw->samples;
to_grab -= chunk;
}
diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c
index 373e4c4..a5c0d6b 100644
--- a/audio/spiceaudio.c
+++ b/audio/spiceaudio.c
@@ -268,11 +268,10 @@ static int line_in_run (HWVoiceIn *hw)
len[1] = 0;
}
- hw->conv (hw->conv_buf + hw->wpos, samples, len[0], &nominal_volume);
+ hw->conv (hw->conv_buf + hw->wpos, samples, len[0]);
if (len[1]) {
- hw->conv (hw->conv_buf, samples + len[0], len[1],
- &nominal_volume);
+ hw->conv (hw->conv_buf, samples + len[0], len[1]);
}
hw->wpos = (hw->wpos + num_samples) % hw->samples;
diff --git a/audio/winwaveaudio.c b/audio/winwaveaudio.c
index cdf483b..e5ad3c6 100644
--- a/audio/winwaveaudio.c
+++ b/audio/winwaveaudio.c
@@ -581,8 +581,7 @@ static int winwave_run_in (HWVoiceIn *hw)
int conv = audio_MIN (left, decr);
hw->conv (hw->conv_buf + hw->wpos,
advance (wave->pcm_buf, wave->rpos << hw->info.shift),
- conv,
- &nominal_volume);
+ conv);
wave->rpos = (wave->rpos + conv) % hw->samples;
hw->wpos = (hw->wpos + conv) % hw->samples;
commit 0f136d9e060ad879d0b840274ddfd1955e24fc10
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Wed Jan 12 14:55:36 2011 +0100
disas: remove opcode printing on ARM hosts
Following commit 5d48e9174e3bfa8655e1dc8f80887acd9040b427, it's possible
to remove the hack that used to display the opcodes on ARM hosts only.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/disas.c b/disas.c
index dd2db14..c76f36f 100644
--- a/disas.c
+++ b/disas.c
@@ -307,11 +307,6 @@ void disas(FILE *out, void *code, unsigned long size)
#endif
for (pc = (unsigned long)code; size > 0; pc += count, size -= count) {
fprintf(out, "0x%08lx: ", pc);
-#ifdef __arm__
- /* since data is included in the code, it is better to
- display code data too */
- fprintf(out, "%08x ", (int)bfd_getl32((const bfd_byte *)pc));
-#endif
count = print_insn(pc, &disasm_info);
fprintf(out, "\n");
if (count < 0)
commit 5d48e9174e3bfa8655e1dc8f80887acd9040b427
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Mon Jan 10 16:16:26 2011 +0000
arm-dis: Include opcode hex when doing disassembly
Enhance the ARM disassembler used for debugging so that it includes
the hex dump of the opcode as well as the symbolic disassembly.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/arm-dis.c b/arm-dis.c
index af21739..3ece02c 100644
--- a/arm-dis.c
+++ b/arm-dis.c
@@ -4101,6 +4101,30 @@ print_insn_arm (bfd_vma pc, struct disassemble_info *info)
addresses, since the addend is not currently pc-relative. */
pc = 0;
+ /* We include the hexdump of the instruction. The format here
+ matches that used by objdump and the ARM ARM (in particular,
+ 32 bit Thumb instructions are displayed as pairs of halfwords,
+ not as a single word.) */
+ if (is_thumb)
+ {
+ if (size == 2)
+ {
+ info->fprintf_func(info->stream, "%04lx ",
+ ((unsigned long)given) & 0xffff);
+ }
+ else
+ {
+ info->fprintf_func(info->stream, "%04lx %04lx ",
+ (((unsigned long)given) >> 16) & 0xffff,
+ ((unsigned long)given) & 0xffff);
+ }
+ }
+ else
+ {
+ info->fprintf_func(info->stream, "%08lx ",
+ ((unsigned long)given) & 0xffffffff);
+ }
+
printer (pc, info, given);
if (is_thumb)
commit ace1318b8ea95efa332fb3e8e159924d4f928753
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Jan 12 11:34:50 2011 +0100
usb: zap pdev from usbport
It isn't needed any more.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index f89176b..6e2e5fd 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -120,11 +120,10 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name)
}
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
- USBDevice *pdev, USBPortOps *ops, int speedmask)
+ USBPortOps *ops, int speedmask)
{
port->opaque = opaque;
port->index = index;
- port->pdev = pdev;
port->opaque = opaque;
port->index = index;
port->ops = ops;
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 387c40c..78698ca 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -536,7 +536,7 @@ static int usb_hub_initfn(USBDevice *dev)
for (i = 0; i < NUM_PORTS; i++) {
port = &s->ports[i];
usb_register_port(usb_bus_from_device(dev),
- &port->port, s, i, &s->dev, &usb_hub_port_ops,
+ &port->port, s, i, &usb_hub_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
port->wPortStatus = PORT_STAT_POWER;
port->wPortChange = 0;
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 4b5f35b..782cfa2 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -349,7 +349,7 @@ struct MUSBState {
}
usb_bus_new(&s->bus, NULL /* FIXME */);
- usb_register_port(&s->bus, &s->port, s, 0, NULL, &musb_port_ops,
+ usb_register_port(&s->bus, &s->port, s, 0, &musb_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
usb_port_location(&s->port, NULL, 1);
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 6344f81..09ea0b6 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1699,7 +1699,7 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
usb_bus_new(&ohci->bus, dev);
ohci->num_ports = num_ports;
for (i = 0; i < num_ports; i++) {
- usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, NULL, &ohci_port_ops,
+ usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, &ohci_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
usb_port_location(&ohci->rhport[i].port, NULL, i+1);
}
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 6db1960..b384e1d 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1129,7 +1129,7 @@ static int usb_uhci_common_initfn(UHCIState *s)
usb_bus_new(&s->bus, &s->dev.qdev);
for(i = 0; i < NB_PORTS; i++) {
- usb_register_port(&s->bus, &s->ports[i].port, s, i, NULL, &uhci_port_ops,
+ usb_register_port(&s->bus, &s->ports[i].port, s, i, &uhci_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
usb_port_location(&s->ports[i].port, NULL, i+1);
}
diff --git a/hw/usb.h b/hw/usb.h
index c6e3e25..5c1da3e 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -244,7 +244,6 @@ struct USBPort {
char path[16];
USBPortOps *ops;
void *opaque;
- USBDevice *pdev;
int index; /* internal port index, may be used with the opaque */
QTAILQ_ENTRY(USBPort) next;
};
@@ -355,7 +354,7 @@ USBDevice *usb_create(USBBus *bus, const char *name);
USBDevice *usb_create_simple(USBBus *bus, const char *name);
USBDevice *usbdevice_create(const char *cmdline);
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
- USBDevice *pdev, USBPortOps *ops, int speedmask);
+ USBPortOps *ops, int speedmask);
void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr);
void usb_unregister_port(USBBus *bus, USBPort *port);
int usb_device_attach(USBDevice *dev);
commit 70d31cb22cb67745741b2bb349c9c7c3a184f88b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Jan 12 10:58:27 2011 +0100
usb: rewrite fw path, fix numbering
This patch rewrites the firmware path code to use the physical port
location tracking just added to the qemu usb core. It also fixes the
port numbering to start with "1" in the firmware path.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 1f59f9a..f89176b 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -7,14 +7,14 @@
static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
static char *usb_get_dev_path(DeviceState *dev);
-static char *usbbus_get_fw_dev_path(DeviceState *dev);
+static char *usb_get_fw_dev_path(DeviceState *qdev);
static struct BusInfo usb_bus_info = {
.name = "USB",
.size = sizeof(USBBus),
.print_dev = usb_bus_dev_print,
.get_dev_path = usb_get_dev_path,
- .get_fw_dev_path = usbbus_get_fw_dev_path,
+ .get_fw_dev_path = usb_get_fw_dev_path,
.props = (Property[]) {
DEFINE_PROP_STRING("port", USBDevice, port_path),
DEFINE_PROP_END_OF_LIST()
@@ -279,6 +279,30 @@ static char *usb_get_dev_path(DeviceState *qdev)
return qemu_strdup(dev->port->path);
}
+static char *usb_get_fw_dev_path(DeviceState *qdev)
+{
+ USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+ char *fw_path, *in;
+ int pos = 0;
+ long nr;
+
+ fw_path = qemu_malloc(32 + strlen(dev->port->path) * 6);
+ in = dev->port->path;
+ while (true) {
+ nr = strtol(in, &in, 10);
+ if (in[0] == '.') {
+ /* some hub between root port and device */
+ pos += sprintf(fw_path + pos, "hub@%ld/", nr);
+ in++;
+ } else {
+ /* the device itself */
+ pos += sprintf(fw_path + pos, "%s@%ld", qdev_fw_name(qdev), nr);
+ break;
+ }
+ }
+ return fw_path;
+}
+
void usb_info(Monitor *mon)
{
USBBus *bus;
@@ -351,43 +375,3 @@ USBDevice *usbdevice_create(const char *cmdline)
}
return usb->usbdevice_init(params);
}
-
-static int usbbus_get_fw_dev_path_helper(USBDevice *d, USBBus *bus, char *p,
- int len)
-{
- int l = 0;
- USBPort *port;
-
- QTAILQ_FOREACH(port, &bus->used, next) {
- if (port->dev == d) {
- if (port->pdev) {
- l = usbbus_get_fw_dev_path_helper(port->pdev, bus, p, len);
- }
- l += snprintf(p + l, len - l, "%s@%x/", qdev_fw_name(&d->qdev),
- port->index);
- break;
- }
- }
-
- return l;
-}
-
-static char *usbbus_get_fw_dev_path(DeviceState *dev)
-{
- USBDevice *d = (USBDevice*)dev;
- USBBus *bus = usb_bus_from_device(d);
- char path[100];
- int l;
-
- assert(d->attached != 0);
-
- l = usbbus_get_fw_dev_path_helper(d, bus, path, sizeof(path));
-
- if (l == 0) {
- abort();
- }
-
- path[l-1] = '\0';
-
- return strdup(path);
-}
commit 56779034530944eb6171d843f652f3fba710ed30
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Mon Jan 10 18:30:05 2011 +0100
tcg arm/mips/ia64: add a comment about retranslation and caches
Add a comment about cache coherency and retranslation, so that people
developping new targets based on existing ones are warned of the issue.
Acked-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 1eb5605..918e2f7 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -352,6 +352,9 @@ static inline void tcg_out_b(TCGContext *s, int cond, int32_t offset)
static inline void tcg_out_b_noaddr(TCGContext *s, int cond)
{
+ /* We pay attention here to not modify the branch target by skipping
+ the corresponding bytes. This ensure that caches and memory are
+ kept coherent during retranslation. */
#ifdef HOST_WORDS_BIGENDIAN
tcg_out8(s, (cond << 4) | 0x0a);
s->code_ptr += 3;
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index e2e44f7..8dac7f7 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -871,6 +871,9 @@ static void tcg_out_br(TCGContext *s, int label_index)
{
TCGLabel *l = &s->labels[label_index];
+ /* We pay attention here to not modify the branch target by reading
+ the existing value and using it again. This ensure that caches and
+ memory are kept coherent during retranslation. */
tcg_out_bundle(s, mmB,
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 4e92a50..e04b0dc 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -351,7 +351,9 @@ static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int i
*/
static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
{
- /* We need to keep the offset unchanged for retranslation */
+ /* We pay attention here to not modify the branch target by reading
+ the existing value and using it again. This ensure that caches and
+ memory are kept coherent during retranslation. */
uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
tcg_out_opc_imm(s, opc, rt, rs, offset);
commit dace20dcc98f90a931e88aa641f5633cdcf30c30
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Mon Jan 10 13:11:24 2011 +0000
linux-user: Add configure check for linux/fiemap.h and IOC_FS_FIEMAP
Add a configure check for the existence of linux/fiemap.h and the
IOC_FS_FIEMAP ioctl. This fixes a compilation failure on Linux
systems which don't have that header file.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 831a741..438219b 100755
--- a/configure
+++ b/configure
@@ -2090,6 +2090,23 @@ if compile_prog "$ARCH_CFLAGS" "" ; then
sync_file_range=yes
fi
+# check for linux/fiemap.h and FS_IOC_FIEMAP
+fiemap=no
+cat > $TMPC << EOF
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include <linux/fiemap.h>
+
+int main(void)
+{
+ ioctl(0, FS_IOC_FIEMAP, 0);
+ return 0;
+}
+EOF
+if compile_prog "$ARCH_CFLAGS" "" ; then
+ fiemap=yes
+fi
+
# check for dup3
dup3=no
cat > $TMPC << EOF
@@ -2631,6 +2648,9 @@ fi
if test "$sync_file_range" = "yes" ; then
echo "CONFIG_SYNC_FILE_RANGE=y" >> $config_host_mak
fi
+if test "$fiemap" = "yes" ; then
+ echo "CONFIG_FIEMAP=y" >> $config_host_mak
+fi
if test "$dup3" = "yes" ; then
echo "CONFIG_DUP3=y" >> $config_host_mak
fi
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 538e257..acff781 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -76,7 +76,7 @@
#ifdef FIGETBSZ
IOCTL(FIGETBSZ, IOC_R, MK_PTR(TYPE_LONG))
#endif
-#ifdef FS_IOC_FIEMAP
+#ifdef CONFIG_FIEMAP
IOCTL_SPECIAL(FS_IOC_FIEMAP, IOC_W | IOC_R, do_ioctl_fs_ioc_fiemap,
MK_PTR(MK_STRUCT(STRUCT_fiemap)))
#endif
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f10e17a..499c4d7 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -83,7 +83,9 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
#include <linux/kd.h>
#include <linux/mtio.h>
#include <linux/fs.h>
+#if defined(CONFIG_FIEMAP)
#include <linux/fiemap.h>
+#endif
#include <linux/fb.h>
#include <linux/vt.h>
#include "linux_loop.h"
@@ -2986,6 +2988,7 @@ struct IOCTLEntry {
#define MAX_STRUCT_SIZE 4096
+#ifdef CONFIG_FIEMAP
/* So fiemap access checks don't overflow on 32 bit systems.
* This is very slightly smaller than the limit imposed by
* the underlying kernel.
@@ -3072,6 +3075,7 @@ static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
}
return ret;
}
+#endif
static IOCTLEntry ioctl_entries[] = {
#define IOCTL(cmd, access, ...) \
commit 0322b26e2d451c3c0fe5f54b1ff4fa18a17525aa
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Sat Jan 8 16:01:16 2011 +0000
ARM: Fix decoding of VQSHL/VQSHLU immediate forms
Fix errors in the decoding of ARM VQSHL/VQSHLU immediate forms,
including using the new VQSHLU helper functions where appropriate.
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 2ce82f3..57664bc 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4652,14 +4652,22 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
case 5: /* VSHL, VSLI */
gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
break;
- case 6: /* VQSHL */
- if (u)
- gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
- else
- gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
+ case 6: /* VQSHLU */
+ if (u) {
+ gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
+ cpu_V0, cpu_V1);
+ } else {
+ return 1;
+ }
break;
- case 7: /* VQSHLU */
- gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
+ case 7: /* VQSHL */
+ if (u) {
+ gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
+ cpu_V0, cpu_V1);
+ } else {
+ gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
+ cpu_V0, cpu_V1);
+ }
break;
}
if (op == 1 || op == 3) {
@@ -4698,17 +4706,30 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
default: return 1;
}
break;
- case 6: /* VQSHL */
- GEN_NEON_INTEGER_OP_ENV(qshl);
- break;
- case 7: /* VQSHLU */
+ case 6: /* VQSHLU */
+ if (!u) {
+ return 1;
+ }
switch (size) {
- case 0: gen_helper_neon_qshl_u8(tmp, cpu_env, tmp, tmp2); break;
- case 1: gen_helper_neon_qshl_u16(tmp, cpu_env, tmp, tmp2); break;
- case 2: gen_helper_neon_qshl_u32(tmp, cpu_env, tmp, tmp2); break;
- default: return 1;
+ case 0:
+ gen_helper_neon_qshlu_s8(tmp, cpu_env,
+ tmp, tmp2);
+ break;
+ case 1:
+ gen_helper_neon_qshlu_s16(tmp, cpu_env,
+ tmp, tmp2);
+ break;
+ case 2:
+ gen_helper_neon_qshlu_s32(tmp, cpu_env,
+ tmp, tmp2);
+ break;
+ default:
+ return 1;
}
break;
+ case 7: /* VQSHL */
+ GEN_NEON_INTEGER_OP_ENV(qshl);
+ break;
}
dead_tmp(tmp2);
commit 4ca4502c93a7ebc358d4e3b5574574e1d84f64b2
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date: Sat Jan 8 16:01:15 2011 +0000
ARM: add neon helpers for VQSHLU
Add neon helper functions to implement VQSHLU, which is a
signed-to-unsigned version of VQSHL available only as an
immediate form.
Signed-off-by: Juha Riihimäki <juha.riihimaki at nokia.com>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index 0d1bc47..b88ebae 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -249,6 +249,10 @@ DEF_HELPER_3(neon_qshl_u32, i32, env, i32, i32)
DEF_HELPER_3(neon_qshl_s32, i32, env, i32, i32)
DEF_HELPER_3(neon_qshl_u64, i64, env, i64, i64)
DEF_HELPER_3(neon_qshl_s64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qshlu_s8, i32, env, i32, i32);
+DEF_HELPER_3(neon_qshlu_s16, i32, env, i32, i32);
+DEF_HELPER_3(neon_qshlu_s32, i32, env, i32, i32);
+DEF_HELPER_3(neon_qshlu_s64, i64, env, i64, i64);
DEF_HELPER_3(neon_qrshl_u8, i32, env, i32, i32)
DEF_HELPER_3(neon_qrshl_s8, i32, env, i32, i32)
DEF_HELPER_3(neon_qrshl_u16, i32, env, i32, i32)
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index dae063e..20f3c16 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -632,6 +632,53 @@ uint64_t HELPER(neon_qshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
return val;
}
+#define NEON_FN(dest, src1, src2) do { \
+ if (src1 & (1 << (sizeof(src1) * 8 - 1))) { \
+ SET_QC(); \
+ dest = 0; \
+ } else { \
+ int8_t tmp; \
+ tmp = (int8_t)src2; \
+ if (tmp >= (ssize_t)sizeof(src1) * 8) { \
+ if (src1) { \
+ SET_QC(); \
+ dest = ~0; \
+ } else { \
+ dest = 0; \
+ } \
+ } else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \
+ dest = 0; \
+ } else if (tmp < 0) { \
+ dest = src1 >> -tmp; \
+ } else { \
+ dest = src1 << tmp; \
+ if ((dest >> tmp) != src1) { \
+ SET_QC(); \
+ dest = ~0; \
+ } \
+ } \
+ }} while (0)
+NEON_VOP_ENV(qshlu_s8, neon_u8, 4)
+NEON_VOP_ENV(qshlu_s16, neon_u16, 2)
+#undef NEON_FN
+
+uint32_t HELPER(neon_qshlu_s32)(CPUState *env, uint32_t valop, uint32_t shiftop)
+{
+ if ((int32_t)valop < 0) {
+ SET_QC();
+ return 0;
+ }
+ return helper_neon_qshl_u32(env, valop, shiftop);
+}
+
+uint64_t HELPER(neon_qshlu_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
+{
+ if ((int64_t)valop < 0) {
+ SET_QC();
+ return 0;
+ }
+ return helper_neon_qshl_u64(env, valop, shiftop);
+}
/* FIXME: This is wrong. */
#define NEON_FN(dest, src1, src2) do { \
commit 5f69076b8dda325dcbbc87bdb00e04ffac0f6137
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Dec 10 11:43:35 2010 +0100
usb: add port property.
This allows to explictily set the physical port where you want to
plug the usb device. Example:
-device usb-tablet,bus=usb.0,port=2
With explicit port addressing qemu can and will not automagically add
USB Hubs. This means that:
(a) You can plug two devices of your choice into the two uhci
root ports.
(b) If you want plug in more that two devices you have to care
about adding a hub yourself.
Plugging a hub works this way:
-device usb-hub,bus=usb.0,port=1
Use this to add a device to the hub:
-device usb-tablet,bus=usb.0,port=1.1
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 0cb03c9..1f59f9a 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -15,6 +15,10 @@ static struct BusInfo usb_bus_info = {
.print_dev = usb_bus_dev_print,
.get_dev_path = usb_get_dev_path,
.get_fw_dev_path = usbbus_get_fw_dev_path,
+ .props = (Property[]) {
+ DEFINE_PROP_STRING("port", USBDevice, port_path),
+ DEFINE_PROP_END_OF_LIST()
+ },
};
static int next_usb_bus = 0;
static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
@@ -157,9 +161,22 @@ static void do_attach(USBDevice *dev)
dev->product_desc);
return;
}
- dev->attached++;
+ if (dev->port_path) {
+ QTAILQ_FOREACH(port, &bus->free, next) {
+ if (strcmp(port->path, dev->port_path) == 0) {
+ break;
+ }
+ }
+ if (port == NULL) {
+ fprintf(stderr, "Warning: usb port %s (bus %s) not found\n",
+ dev->port_path, bus->qbus.name);
+ return;
+ }
+ } else {
+ port = QTAILQ_FIRST(&bus->free);
+ }
- port = QTAILQ_FIRST(&bus->free);
+ dev->attached++;
QTAILQ_REMOVE(&bus->free, port, next);
bus->nfree--;
@@ -173,8 +190,9 @@ int usb_device_attach(USBDevice *dev)
{
USBBus *bus = usb_bus_from_device(dev);
- if (bus->nfree == 1) {
- /* Create a new hub and chain it on. */
+ if (bus->nfree == 1 && dev->port_path == NULL) {
+ /* Create a new hub and chain it on
+ (unless a physical port location is specified). */
usb_create_simple(bus, "usb-hub");
}
do_attach(dev);
diff --git a/hw/usb.h b/hw/usb.h
index 8fdda29..c6e3e25 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -156,6 +156,7 @@ struct USBDevice {
DeviceState qdev;
USBDeviceInfo *info;
USBPort *port;
+ char *port_path;
void *opaque;
int speed;
commit 86865c5ff16bd1a2ef2b9ce217a7bb8f39e2126c
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Tue Jan 11 16:13:34 2011 +0100
target-sh4: fix fpu disabled/illegal exception
Illegal instructions in a slot delay should generate a slot illegal
instruction exception instead of an illegal instruction exception.
The current PC should be saved before generating such an exception,
but should not be corrected if in a delay slot, given it's already
done in the exception handler do_interrupt().
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index f418139..37915d5 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -469,27 +469,30 @@ static inline void gen_store_fpr64 (TCGv_i64 t, int reg)
#define CHECK_NOT_DELAY_SLOT \
if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) \
{ \
- tcg_gen_movi_i32(cpu_pc, ctx->pc-2); \
+ tcg_gen_movi_i32(cpu_pc, ctx->pc); \
gen_helper_raise_slot_illegal_instruction(); \
ctx->bstate = BS_EXCP; \
return; \
}
-#define CHECK_PRIVILEGED \
- if (IS_USER(ctx)) { \
- tcg_gen_movi_i32(cpu_pc, ctx->pc); \
- gen_helper_raise_illegal_instruction(); \
- ctx->bstate = BS_EXCP; \
- return; \
+#define CHECK_PRIVILEGED \
+ if (IS_USER(ctx)) { \
+ tcg_gen_movi_i32(cpu_pc, ctx->pc); \
+ if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
+ gen_helper_raise_slot_illegal_instruction(); \
+ } else { \
+ gen_helper_raise_illegal_instruction(); \
+ } \
+ ctx->bstate = BS_EXCP; \
+ return; \
}
#define CHECK_FPU_ENABLED \
if (ctx->flags & SR_FD) { \
+ tcg_gen_movi_i32(cpu_pc, ctx->pc); \
if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) { \
- tcg_gen_movi_i32(cpu_pc, ctx->pc-2); \
gen_helper_raise_slot_fpu_disable(); \
} else { \
- tcg_gen_movi_i32(cpu_pc, ctx->pc); \
gen_helper_raise_fpu_disable(); \
} \
ctx->bstate = BS_EXCP; \
@@ -1860,7 +1863,12 @@ static void _decode_opc(DisasContext * ctx)
ctx->opcode, ctx->pc);
fflush(stderr);
#endif
- gen_helper_raise_illegal_instruction();
+ tcg_gen_movi_i32(cpu_pc, ctx->pc);
+ if (ctx->flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) {
+ gen_helper_raise_slot_illegal_instruction();
+ } else {
+ gen_helper_raise_illegal_instruction();
+ }
ctx->bstate = BS_EXCP;
}
commit c7a2196a4fcdaba977b99aca0b6a6de5e5e7f64a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Dec 10 11:37:45 2010 +0100
usb: keep track of physical port address.
Add a path string to USBPort. Add usb_port_location() function to set
the physical location of the usb port. Update all drivers implementing
usb ports to call it. Update the monitor commands to print it. Wind it
up in qdev.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index e94b88d..0cb03c9 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -5,12 +5,15 @@
#include "monitor.h"
static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
+
+static char *usb_get_dev_path(DeviceState *dev);
static char *usbbus_get_fw_dev_path(DeviceState *dev);
static struct BusInfo usb_bus_info = {
.name = "USB",
.size = sizeof(USBBus),
.print_dev = usb_bus_dev_print,
+ .get_dev_path = usb_get_dev_path,
.get_fw_dev_path = usbbus_get_fw_dev_path,
};
static int next_usb_bus = 0;
@@ -126,6 +129,16 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
bus->nfree++;
}
+void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr)
+{
+ if (upstream) {
+ snprintf(downstream->path, sizeof(downstream->path), "%s.%d",
+ upstream->path, portnr);
+ } else {
+ snprintf(downstream->path, sizeof(downstream->path), "%d", portnr);
+ }
+}
+
void usb_unregister_port(USBBus *bus, USBPort *port)
{
if (port->dev)
@@ -235,12 +248,19 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
USBBus *bus = usb_bus_from_device(dev);
- monitor_printf(mon, "%*saddr %d.%d, speed %s, name %s%s\n",
+ monitor_printf(mon, "%*saddr %d.%d, port %s, speed %s, name %s%s\n",
indent, "", bus->busnr, dev->addr,
+ dev->port ? dev->port->path : "-",
usb_speed(dev->speed), dev->product_desc,
dev->attached ? ", attached" : "");
}
+static char *usb_get_dev_path(DeviceState *qdev)
+{
+ USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
+ return qemu_strdup(dev->port->path);
+}
+
void usb_info(Monitor *mon)
{
USBBus *bus;
@@ -257,8 +277,8 @@ void usb_info(Monitor *mon)
dev = port->dev;
if (!dev)
continue;
- monitor_printf(mon, " Device %d.%d, Speed %s Mb/s, Product %s\n",
- bus->busnr, dev->addr, usb_speed(dev->speed),
+ monitor_printf(mon, " Device %d.%d, Port %s, Speed %s Mb/s, Product %s\n",
+ bus->busnr, dev->addr, port->path, usb_speed(dev->speed),
dev->product_desc);
}
}
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index ba712d6..387c40c 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -256,6 +256,16 @@ static void usb_hub_wakeup(USBDevice *dev)
}
}
+static void usb_hub_handle_attach(USBDevice *dev)
+{
+ USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
+ int i;
+
+ for (i = 0; i < NUM_PORTS; i++) {
+ usb_port_location(&s->ports[i].port, dev->port, i+1);
+ }
+}
+
static void usb_hub_handle_reset(USBDevice *dev)
{
/* XXX: do it */
@@ -542,6 +552,7 @@ static struct USBDeviceInfo hub_info = {
.usb_desc = &desc_hub,
.init = usb_hub_initfn,
.handle_packet = usb_hub_handle_packet,
+ .handle_attach = usb_hub_handle_attach,
.handle_reset = usb_hub_handle_reset,
.handle_control = usb_hub_handle_control,
.handle_data = usb_hub_handle_data,
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 87eb9ca..4b5f35b 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -351,6 +351,7 @@ struct MUSBState {
usb_bus_new(&s->bus, NULL /* FIXME */);
usb_register_port(&s->bus, &s->port, s, 0, NULL, &musb_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+ usb_port_location(&s->port, NULL, 1);
return s;
}
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 0d42716..6344f81 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1701,6 +1701,7 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
for (i = 0; i < num_ports; i++) {
usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, NULL, &ohci_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+ usb_port_location(&ohci->rhport[i].port, NULL, i+1);
}
ohci->async_td = 0;
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 253561f..6db1960 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1131,6 +1131,7 @@ static int usb_uhci_common_initfn(UHCIState *s)
for(i = 0; i < NB_PORTS; i++) {
usb_register_port(&s->bus, &s->ports[i].port, s, i, NULL, &uhci_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
+ usb_port_location(&s->ports[i].port, NULL, i+1);
}
s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
s->expire_time = qemu_get_clock(vm_clock) +
diff --git a/hw/usb.h b/hw/usb.h
index 99139e2..8fdda29 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -240,6 +240,7 @@ typedef struct USBPortOps {
struct USBPort {
USBDevice *dev;
int speedmask;
+ char path[16];
USBPortOps *ops;
void *opaque;
USBDevice *pdev;
@@ -354,6 +355,7 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name);
USBDevice *usbdevice_create(const char *cmdline);
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
USBDevice *pdev, USBPortOps *ops, int speedmask);
+void usb_port_location(USBPort *downstream, USBPort *upstream, int portnr);
void usb_unregister_port(USBBus *bus, USBPort *port);
int usb_device_attach(USBDevice *dev);
int usb_device_detach(USBDevice *dev);
commit fa7935c1e1f84b600fcb1983485352b8d99e01d3
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Thu Dec 9 23:31:49 2010 +0100
usb storage: handle long responses
The scsi layer may return us more data than the guests wants to have.
Handle this by just ignoring the extra bytes and calling the
{read,write}_data callback to finish the request.
Seen happening in real life with some extended inquiry command.
With this patch applied the linux kernel stops reseting the device
once at boot.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 28c12dd..729d96c 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -187,7 +187,7 @@ static void usb_msd_copy_data(MSDState *s)
s->usb_buf += len;
s->scsi_buf += len;
s->data_len -= len;
- if (s->scsi_len == 0) {
+ if (s->scsi_len == 0 || s->data_len == 0) {
if (s->mode == USB_MSDM_DATAIN) {
s->scsi_dev->info->read_data(s->scsi_dev, s->tag);
} else if (s->mode == USB_MSDM_DATAOUT) {
@@ -434,7 +434,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
break;
case USB_MSDM_DATAIN:
- DPRINTF("Data in %d/%d\n", len, s->data_len);
+ DPRINTF("Data in %d/%d, scsi_len %d\n", len, s->data_len, s->scsi_len);
if (len > s->data_len)
len = s->data_len;
s->usb_buf = data;
commit ab4797ad2ec34e63ee8751fbd3e5d0a9888eaf4a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Thu Dec 9 10:36:35 2010 +0100
usb storage: fix status reporting
Change usb_msd_send_status() to take a pointer to the status packet
instead of writing the status to s->usb_buf which might not point
to the correct location.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 7b8189f..28c12dd 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -196,15 +196,18 @@ static void usb_msd_copy_data(MSDState *s)
}
}
-static void usb_msd_send_status(MSDState *s)
+static void usb_msd_send_status(MSDState *s, USBPacket *p)
{
struct usb_msd_csw csw;
+ int len;
csw.sig = cpu_to_le32(0x53425355);
csw.tag = cpu_to_le32(s->tag);
csw.residue = s->residue;
csw.status = s->result;
- memcpy(s->usb_buf, &csw, 13);
+
+ len = MIN(sizeof(csw), p->len);
+ memcpy(p->data, &csw, len);
}
static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
@@ -224,7 +227,7 @@ static void usb_msd_command_complete(SCSIBus *bus, int reason, uint32_t tag,
if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
/* A deferred packet with no write data remaining must be
the status read packet. */
- usb_msd_send_status(s);
+ usb_msd_send_status(s, p);
s->mode = USB_MSDM_CBW;
} else {
if (s->data_len) {
@@ -425,9 +428,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
if (len < 13)
goto fail;
- s->usb_len = len;
- s->usb_buf = data;
- usb_msd_send_status(s);
+ usb_msd_send_status(s, p);
s->mode = USB_MSDM_CBW;
ret = 13;
break;
commit ca0c730df977abd7ca24afd17fa640f1af47f0b1
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Dec 3 17:12:49 2010 +0100
usb storage: high speed support
Add high speed support to the usb mass storage device. With this patch
applied the linux kernel recognises the usb storage device as highspeed
capable device and suggests to connect it to a highspeed port instead of
the uhci. Tested with both uhci and (not-yet submitted) ehci.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 74e657e..7b8189f 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -77,15 +77,19 @@ enum {
STR_MANUFACTURER = 1,
STR_PRODUCT,
STR_SERIALNUMBER,
+ STR_CONFIG_FULL,
+ STR_CONFIG_HIGH,
};
static const USBDescStrings desc_strings = {
[STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
[STR_PRODUCT] = "QEMU USB HARDDRIVE",
[STR_SERIALNUMBER] = "1",
+ [STR_CONFIG_FULL] = "Full speed config (usb 1.1)",
+ [STR_CONFIG_HIGH] = "High speed config (usb 2.0)",
};
-static const USBDescIface desc_iface0 = {
+static const USBDescIface desc_iface_full = {
.bInterfaceNumber = 0,
.bNumEndpoints = 2,
.bInterfaceClass = USB_CLASS_MASS_STORAGE,
@@ -104,16 +108,51 @@ static const USBDescIface desc_iface0 = {
}
};
-static const USBDescDevice desc_device = {
- .bcdUSB = 0x0100,
+static const USBDescDevice desc_device_full = {
+ .bcdUSB = 0x0200,
.bMaxPacketSize0 = 8,
.bNumConfigurations = 1,
.confs = (USBDescConfig[]) {
{
.bNumInterfaces = 1,
.bConfigurationValue = 1,
+ .iConfiguration = STR_CONFIG_FULL,
.bmAttributes = 0xc0,
- .ifs = &desc_iface0,
+ .ifs = &desc_iface_full,
+ },
+ },
+};
+
+static const USBDescIface desc_iface_high = {
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_MASS_STORAGE,
+ .bInterfaceSubClass = 0x06, /* SCSI */
+ .bInterfaceProtocol = 0x50, /* Bulk */
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | 0x01,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 512,
+ },{
+ .bEndpointAddress = USB_DIR_OUT | 0x02,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 512,
+ },
+ }
+};
+
+static const USBDescDevice desc_device_high = {
+ .bcdUSB = 0x0200,
+ .bMaxPacketSize0 = 64,
+ .bNumConfigurations = 1,
+ .confs = (USBDescConfig[]) {
+ {
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .iConfiguration = STR_CONFIG_HIGH,
+ .bmAttributes = 0xc0,
+ .ifs = &desc_iface_high,
},
},
};
@@ -127,7 +166,8 @@ static const USBDesc desc = {
.iProduct = STR_PRODUCT,
.iSerialNumber = STR_SERIALNUMBER,
},
- .full = &desc_device,
+ .full = &desc_device_full,
+ .high = &desc_device_high,
.str = desc_strings,
};
@@ -558,6 +598,7 @@ static struct USBDeviceInfo msd_info = {
.usb_desc = &desc,
.init = usb_msd_initfn,
.handle_packet = usb_generic_handle_packet,
+ .handle_attach = usb_desc_attach,
.handle_reset = usb_msd_handle_reset,
.handle_control = usb_msd_handle_control,
.handle_data = usb_msd_handle_data,
commit 25620cba94d7ca126a24d74ce6f2ac42aa9a2fe8
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Dec 8 17:35:22 2010 +0100
usb: add device qualifier support
Add support for device_qualifier and other_speed_config descriptors.
These are used to query the "other speed" configuration of usb 2.0
devices, i.e. in high-speed mode they return the full-speed
configuration and visa versa.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index f01e1cf..62591f2 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -48,6 +48,30 @@ int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
return bLength;
}
+int usb_desc_device_qualifier(const USBDescDevice *dev,
+ uint8_t *dest, size_t len)
+{
+ uint8_t bLength = 0x0a;
+
+ if (len < bLength) {
+ return -1;
+ }
+
+ dest[0x00] = bLength;
+ dest[0x01] = USB_DT_DEVICE_QUALIFIER;
+
+ dest[0x02] = usb_lo(dev->bcdUSB);
+ dest[0x03] = usb_hi(dev->bcdUSB);
+ dest[0x04] = dev->bDeviceClass;
+ dest[0x05] = dev->bDeviceSubClass;
+ dest[0x06] = dev->bDeviceProtocol;
+ dest[0x07] = dev->bMaxPacketSize0;
+ dest[0x08] = dev->bNumConfigurations;
+ dest[0x09] = 0; /* reserved */
+
+ return bLength;
+}
+
int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
{
uint8_t bLength = 0x09;
@@ -263,11 +287,18 @@ int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
{
const USBDesc *desc = dev->info->usb_desc;
+ const USBDescDevice *other_dev;
uint8_t buf[256];
uint8_t type = value >> 8;
uint8_t index = value & 0xff;
int ret = -1;
+ if (dev->speed == USB_SPEED_HIGH) {
+ other_dev = dev->info->usb_desc->full;
+ } else {
+ other_dev = dev->info->usb_desc->high;
+ }
+
switch(type) {
case USB_DT_DEVICE:
ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
@@ -283,6 +314,21 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
ret = usb_desc_string(dev, index, buf, sizeof(buf));
trace_usb_desc_string(dev->addr, index, len, ret);
break;
+
+ case USB_DT_DEVICE_QUALIFIER:
+ if (other_dev != NULL) {
+ ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
+ }
+ trace_usb_desc_device_qualifier(dev->addr, len, ret);
+ break;
+ case USB_DT_OTHER_SPEED_CONFIG:
+ if (other_dev != NULL && index < other_dev->bNumConfigurations) {
+ ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf));
+ buf[0x01] = USB_DT_OTHER_SPEED_CONFIG;
+ }
+ trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
+ break;
+
default:
fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
dev->addr, type, len);
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
index 484c7c7..ac734ab 100644
--- a/hw/usb-desc.h
+++ b/hw/usb-desc.h
@@ -72,6 +72,8 @@ struct USBDesc {
/* generate usb packages from structs */
int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
uint8_t *dest, size_t len);
+int usb_desc_device_qualifier(const USBDescDevice *dev,
+ uint8_t *dest, size_t len);
int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len);
int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len);
int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
diff --git a/hw/usb.h b/hw/usb.h
index 892ff72..99139e2 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -122,6 +122,8 @@
#define USB_DT_STRING 0x03
#define USB_DT_INTERFACE 0x04
#define USB_DT_ENDPOINT 0x05
+#define USB_DT_DEVICE_QUALIFIER 0x06
+#define USB_DT_OTHER_SPEED_CONFIG 0x07
#define USB_ENDPOINT_XFER_CONTROL 0
#define USB_ENDPOINT_XFER_ISOC 1
diff --git a/trace-events b/trace-events
index 45e7582..19cee6a 100644
--- a/trace-events
+++ b/trace-events
@@ -192,7 +192,9 @@ disable sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64""
# hw/usb-desc.c
disable usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
+disable usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d"
disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
+disable usb_desc_other_speed_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
disable usb_set_addr(int addr) "dev %d"
disable usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d"
commit 32d41919784abe56b10f6d7784c00bb27e4f4d39
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Dec 3 18:07:20 2010 +0100
usb: add usb_desc_attach
Add usb_desc_attach() which sets up the device according to the speed
the usb port is able to handle. This function can be hooked into the
handle_attach callback.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index 56ef734..f01e1cf 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -153,16 +153,46 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
/* ------------------------------------------------------------------ */
-void usb_desc_init(USBDevice *dev)
+static void usb_desc_setdefaults(USBDevice *dev)
{
const USBDesc *desc = dev->info->usb_desc;
assert(desc != NULL);
- dev->speed = USB_SPEED_FULL;
- dev->device = desc->full;
+ switch (dev->speed) {
+ case USB_SPEED_LOW:
+ case USB_SPEED_FULL:
+ dev->device = desc->full;
+ break;
+ case USB_SPEED_HIGH:
+ dev->device = desc->high;
+ break;
+ }
dev->config = dev->device->confs;
}
+void usb_desc_init(USBDevice *dev)
+{
+ dev->speed = USB_SPEED_FULL;
+ usb_desc_setdefaults(dev);
+}
+
+void usb_desc_attach(USBDevice *dev)
+{
+ const USBDesc *desc = dev->info->usb_desc;
+
+ assert(desc != NULL);
+ if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
+ dev->speed = USB_SPEED_HIGH;
+ } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) {
+ dev->speed = USB_SPEED_FULL;
+ } else {
+ fprintf(stderr, "usb: port/device speed mismatch for \"%s\"\n",
+ dev->info->product_desc);
+ return;
+ }
+ usb_desc_setdefaults(dev);
+}
+
void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
{
USBDescString *s;
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
index d441725..484c7c7 100644
--- a/hw/usb-desc.h
+++ b/hw/usb-desc.h
@@ -79,6 +79,7 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
/* control message emulation helpers */
void usb_desc_init(USBDevice *dev);
+void usb_desc_attach(USBDevice *dev);
void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
commit b6f77fbe230ad3e9ec5c9115a1535137d5e5d04b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Dec 3 17:59:36 2010 +0100
usb: add attach callback
Add handle_attach() callback to USBDeviceInfo which is called by the
generic package handler when the device is attached to the usb bus
(i.e. plugged into a port).
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb.c b/hw/usb.c
index ba720b4..82a6217 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -194,6 +194,9 @@ int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
switch(p->pid) {
case USB_MSG_ATTACH:
s->state = USB_STATE_ATTACHED;
+ if (s->info->handle_attach) {
+ s->info->handle_attach(s);
+ }
return 0;
case USB_MSG_DETACH:
@@ -204,7 +207,9 @@ int usb_generic_handle_packet(USBDevice *s, USBPacket *p)
s->remote_wakeup = 0;
s->addr = 0;
s->state = USB_STATE_DEFAULT;
- s->info->handle_reset(s);
+ if (s->info->handle_reset) {
+ s->info->handle_reset(s);
+ }
return 0;
}
diff --git a/hw/usb.h b/hw/usb.h
index 407a114..892ff72 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -194,6 +194,11 @@ struct USBDeviceInfo {
void (*handle_destroy)(USBDevice *dev);
/*
+ * Attach the device
+ */
+ void (*handle_attach)(USBDevice *dev);
+
+ /*
* Reset the device
*/
void (*handle_reset)(USBDevice *dev);
commit 843d4e0c633824a11c4067d0e84bd683520b5d39
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Dec 3 17:30:13 2010 +0100
usb: add speed mask to ports
Add a field to usb ports indicating the speed(s) they are
able to handle.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 9dc8793..e94b88d 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -113,7 +113,7 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name)
}
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
- USBDevice *pdev, USBPortOps *ops)
+ USBDevice *pdev, USBPortOps *ops, int speedmask)
{
port->opaque = opaque;
port->index = index;
@@ -121,6 +121,7 @@ void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
port->opaque = opaque;
port->index = index;
port->ops = ops;
+ port->speedmask = speedmask;
QTAILQ_INSERT_TAIL(&bus->free, port, next);
bus->nfree++;
}
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 8a80151..ba712d6 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -526,7 +526,8 @@ static int usb_hub_initfn(USBDevice *dev)
for (i = 0; i < NUM_PORTS; i++) {
port = &s->ports[i];
usb_register_port(usb_bus_from_device(dev),
- &port->port, s, i, &s->dev, &usb_hub_port_ops);
+ &port->port, s, i, &s->dev, &usb_hub_port_ops,
+ USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
port->wPortStatus = PORT_STAT_POWER;
port->wPortChange = 0;
}
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 233a265..87eb9ca 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -349,7 +349,8 @@ struct MUSBState {
}
usb_bus_new(&s->bus, NULL /* FIXME */);
- usb_register_port(&s->bus, &s->port, s, 0, NULL, &musb_port_ops);
+ usb_register_port(&s->bus, &s->port, s, 0, NULL, &musb_port_ops,
+ USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
return s;
}
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index c859540..0d42716 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1699,7 +1699,8 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
usb_bus_new(&ohci->bus, dev);
ohci->num_ports = num_ports;
for (i = 0; i < num_ports; i++) {
- usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, NULL, &ohci_port_ops);
+ usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, NULL, &ohci_port_ops,
+ USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
}
ohci->async_td = 0;
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 2d2a9e7..253561f 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1129,7 +1129,8 @@ static int usb_uhci_common_initfn(UHCIState *s)
usb_bus_new(&s->bus, &s->dev.qdev);
for(i = 0; i < NB_PORTS; i++) {
- usb_register_port(&s->bus, &s->ports[i].port, s, i, NULL, &uhci_port_ops);
+ usb_register_port(&s->bus, &s->ports[i].port, s, i, NULL, &uhci_port_ops,
+ USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
}
s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
s->expire_time = qemu_get_clock(vm_clock) +
diff --git a/hw/usb.h b/hw/usb.h
index 250ec71..407a114 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -44,6 +44,12 @@
#define USB_SPEED_LOW 0
#define USB_SPEED_FULL 1
#define USB_SPEED_HIGH 2
+#define USB_SPEED_SUPER 3
+
+#define USB_SPEED_MASK_LOW (1 << USB_SPEED_LOW)
+#define USB_SPEED_MASK_FULL (1 << USB_SPEED_FULL)
+#define USB_SPEED_MASK_HIGH (1 << USB_SPEED_HIGH)
+#define USB_SPEED_MASK_SUPER (1 << USB_SPEED_SUPER)
#define USB_STATE_NOTATTACHED 0
#define USB_STATE_ATTACHED 1
@@ -226,6 +232,7 @@ typedef struct USBPortOps {
/* USB port on which a device can be connected */
struct USBPort {
USBDevice *dev;
+ int speedmask;
USBPortOps *ops;
void *opaque;
USBDevice *pdev;
@@ -339,7 +346,7 @@ USBDevice *usb_create(USBBus *bus, const char *name);
USBDevice *usb_create_simple(USBBus *bus, const char *name);
USBDevice *usbdevice_create(const char *cmdline);
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
- USBDevice *pdev, USBPortOps *ops);
+ USBDevice *pdev, USBPortOps *ops, int speedmask);
void usb_unregister_port(USBBus *bus, USBPort *port);
int usb_device_attach(USBDevice *dev);
int usb_device_detach(USBDevice *dev);
commit 7b074a22dab4bdda9864b933f1bc811a3db42845
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Tue Dec 14 16:46:40 2010 +0100
usb: hid: change serial number to "42".
It would be nice to have some way to signal our hid devices support
remote wakeup. There is a descriptor bit for that of course. Problem
with using is one is that older qemu versions used to set the bit even
though they did *not* support remote wakeup. Bummer.
This patch changes the serial number of our hid devices from "1" to "42"
to signal "it is safe to enable remote wakeup". The serial number was
choosen because it isn't used for anything and it is available in sysfs
so it is easy to match it using udev rules like this:
ACTION=="add", SUBSYSTEM=="usb", \
ATTR{product}=="QEMU USB Tablet", ATTR{serial}=="42", \
RUN+="usb_enable_autosuspend %p"
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 60fa57f..1fec163 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -90,7 +90,7 @@ static const USBDescStrings desc_strings = {
[STR_PRODUCT_MOUSE] = "QEMU USB Mouse",
[STR_PRODUCT_TABLET] = "QEMU USB Tablet",
[STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
- [STR_SERIALNUMBER] = "1",
+ [STR_SERIALNUMBER] = "42", /* == remote wakeup works */
[STR_CONFIG_MOUSE] = "HID Mouse",
[STR_CONFIG_TABLET] = "HID Tablet",
[STR_CONFIG_KEYBOARD] = "HID Keyboard",
commit ac57bbb614ace4f7b8b965562826a7f7fda00cdc
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Dec 1 11:50:04 2010 +0100
usb: hid: remote wakeup support.
Add usb_wakeup() call to the hid driver so remote wakeup actually works.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 1c35960..60fa57f 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -429,6 +429,8 @@ static void usb_hid_changed(USBHIDState *hs)
if (hs->datain)
hs->datain(hs->datain_opaque);
+
+ usb_wakeup(&hs->dev);
}
static void usb_mouse_event(void *opaque,
commit 34239c7bc972735391ca84283f8c8ad908dc61ef
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Dec 15 12:26:59 2010 +0100
usb: hub: remote wakeup support.
This patch makes the usb hub handle remote wakeup requests from devices
properly by updating the port status register and forwarding the wakeup
to the upstream port.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 8837bd9..8a80151 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -245,6 +245,17 @@ static void usb_hub_detach(USBPort *port1)
}
}
+static void usb_hub_wakeup(USBDevice *dev)
+{
+ USBHubState *s = dev->port->opaque;
+ USBHubPort *port = &s->ports[dev->port->index];
+
+ if (port->wPortStatus & PORT_STAT_SUSPEND) {
+ port->wPortChange |= PORT_STAT_C_SUSPEND;
+ usb_wakeup(&s->dev);
+ }
+}
+
static void usb_hub_handle_reset(USBDevice *dev)
{
/* XXX: do it */
@@ -502,6 +513,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
static USBPortOps usb_hub_port_ops = {
.attach = usb_hub_attach,
.detach = usb_hub_detach,
+ .wakeup = usb_hub_wakeup,
};
static int usb_hub_initfn(USBDevice *dev)
commit 9159f6798ebfe0cdcfd1d1fb91c2c08b6d95954a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Dec 1 11:47:40 2010 +0100
usb: uhci: remote wakeup support.
Add support for remote wakeup to the UHCI adapter.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 5e2e34a..2d2a9e7 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -57,13 +57,18 @@
#define TD_CTRL_NAK (1 << 19)
#define TD_CTRL_TIMEOUT (1 << 18)
+#define UHCI_PORT_SUSPEND (1 << 12)
#define UHCI_PORT_RESET (1 << 9)
#define UHCI_PORT_LSDA (1 << 8)
+#define UHCI_PORT_RD (1 << 6)
#define UHCI_PORT_ENC (1 << 3)
#define UHCI_PORT_EN (1 << 2)
#define UHCI_PORT_CSC (1 << 1)
#define UHCI_PORT_CCS (1 << 0)
+#define UHCI_PORT_READ_ONLY (0x1bb)
+#define UHCI_PORT_WRITE_CLEAR (UHCI_PORT_CSC | UHCI_PORT_ENC)
+
#define FRAME_TIMER_FREQ 1000
#define FRAME_MAX_LOOPS 100
@@ -497,9 +502,10 @@ static void uhci_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
usb_send_msg(dev, USB_MSG_RESET);
}
}
- port->ctrl = (port->ctrl & 0x01fb) | (val & ~0x01fb);
+ port->ctrl &= UHCI_PORT_READ_ONLY;
+ port->ctrl |= (val & ~UHCI_PORT_READ_ONLY);
/* some bits are reset when a '1' is written to them */
- port->ctrl &= ~(val & 0x000a);
+ port->ctrl &= ~(val & UHCI_PORT_WRITE_CLEAR);
}
break;
}
@@ -629,6 +635,18 @@ static void uhci_detach(USBPort *port1)
uhci_resume(s);
}
+static void uhci_wakeup(USBDevice *dev)
+{
+ USBBus *bus = usb_bus_from_device(dev);
+ UHCIState *s = container_of(bus, UHCIState, bus);
+ UHCIPort *port = s->ports + dev->port->index;
+
+ if (port->ctrl & UHCI_PORT_SUSPEND && !(port->ctrl & UHCI_PORT_RD)) {
+ port->ctrl |= UHCI_PORT_RD;
+ uhci_resume(s);
+ }
+}
+
static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
{
int i, ret;
@@ -1094,6 +1112,7 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
static USBPortOps uhci_port_ops = {
.attach = uhci_attach,
.detach = uhci_detach,
+ .wakeup = uhci_wakeup,
};
static int usb_uhci_common_initfn(UHCIState *s)
commit 01eacab6e95267fd894d0c1013aa5bf55c320dc8
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Dec 1 11:32:45 2010 +0100
usb: add usb_wakeup() + wakeup callback to port ops
Add wakeup callback to port ops for remote wakeup handling.
Also add a usb_wakeup() function for devices which want
trigger a remote wakeup.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb.c b/hw/usb.c
index 2eda86a..ba720b4 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -49,6 +49,13 @@ void usb_attach(USBPort *port, USBDevice *dev)
}
}
+void usb_wakeup(USBDevice *dev)
+{
+ if (dev->remote_wakeup && dev->port && dev->port->ops->wakeup) {
+ dev->port->ops->wakeup(dev);
+ }
+}
+
/**********************/
/* generic USB device helpers (you are not forced to use them when
diff --git a/hw/usb.h b/hw/usb.h
index 3744d19..250ec71 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -220,6 +220,7 @@ struct USBDeviceInfo {
typedef struct USBPortOps {
void (*attach)(USBPort *port);
void (*detach)(USBPort *port);
+ void (*wakeup)(USBDevice *dev);
} USBPortOps;
/* USB port on which a device can be connected */
@@ -275,6 +276,7 @@ static inline void usb_cancel_packet(USBPacket * p)
}
void usb_attach(USBPort *port, USBDevice *dev);
+void usb_wakeup(USBDevice *dev);
int usb_generic_handle_packet(USBDevice *s, USBPacket *p);
int set_usb_string(uint8_t *buf, const char *str);
void usb_send_msg(USBDevice *dev, int msg);
commit 618c169b577db64ac6589ad48825d2e11760d1a6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Dec 1 11:27:05 2010 +0100
usb: rework attach/detach workflow
Add separate detach callback to USBPortOps, split
uhci/ohci/musb/usbhub attach functions into two.
Move common code to the usb_attach() function, only
the hardware-specific bits remain in the attach/detach
callbacks.
Keep track of the port it is attached to for each usb device.
[ v3: fix tyops in usb-musb.c ]
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index b3d7298..8837bd9 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -218,37 +218,30 @@ static const uint8_t qemu_hub_hub_descriptor[] =
/* DeviceRemovable and PortPwrCtrlMask patched in later */
};
-static void usb_hub_attach(USBPort *port1, USBDevice *dev)
+static void usb_hub_attach(USBPort *port1)
{
USBHubState *s = port1->opaque;
USBHubPort *port = &s->ports[port1->index];
- if (dev) {
- if (port->port.dev)
- usb_attach(port1, NULL);
-
- port->wPortStatus |= PORT_STAT_CONNECTION;
- port->wPortChange |= PORT_STAT_C_CONNECTION;
- if (dev->speed == USB_SPEED_LOW)
- port->wPortStatus |= PORT_STAT_LOW_SPEED;
- else
- port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
- port->port.dev = dev;
- /* send the attach message */
- usb_send_msg(dev, USB_MSG_ATTACH);
+ port->wPortStatus |= PORT_STAT_CONNECTION;
+ port->wPortChange |= PORT_STAT_C_CONNECTION;
+ if (port->port.dev->speed == USB_SPEED_LOW) {
+ port->wPortStatus |= PORT_STAT_LOW_SPEED;
} else {
- dev = port->port.dev;
- if (dev) {
- port->wPortStatus &= ~PORT_STAT_CONNECTION;
- port->wPortChange |= PORT_STAT_C_CONNECTION;
- if (port->wPortStatus & PORT_STAT_ENABLE) {
- port->wPortStatus &= ~PORT_STAT_ENABLE;
- port->wPortChange |= PORT_STAT_C_ENABLE;
- }
- /* send the detach message */
- usb_send_msg(dev, USB_MSG_DETACH);
- port->port.dev = NULL;
- }
+ port->wPortStatus &= ~PORT_STAT_LOW_SPEED;
+ }
+}
+
+static void usb_hub_detach(USBPort *port1)
+{
+ USBHubState *s = port1->opaque;
+ USBHubPort *port = &s->ports[port1->index];
+
+ port->wPortStatus &= ~PORT_STAT_CONNECTION;
+ port->wPortChange |= PORT_STAT_C_CONNECTION;
+ if (port->wPortStatus & PORT_STAT_ENABLE) {
+ port->wPortStatus &= ~PORT_STAT_ENABLE;
+ port->wPortChange |= PORT_STAT_C_ENABLE;
}
}
@@ -508,6 +501,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
static USBPortOps usb_hub_port_ops = {
.attach = usb_hub_attach,
+ .detach = usb_hub_detach,
};
static int usb_hub_initfn(USBDevice *dev)
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 592d3e6..233a265 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -259,10 +259,12 @@
#endif
-static void musb_attach(USBPort *port, USBDevice *dev);
+static void musb_attach(USBPort *port);
+static void musb_detach(USBPort *port);
static USBPortOps musb_port_ops = {
.attach = musb_attach,
+ .detach = musb_detach,
};
typedef struct {
@@ -464,34 +466,20 @@ static void musb_session_update(MUSBState *s, int prev_dev, int prev_sess)
}
/* Attach or detach a device on our only port. */
-static void musb_attach(USBPort *port, USBDevice *dev)
+static void musb_attach(USBPort *port)
{
MUSBState *s = (MUSBState *) port->opaque;
- USBDevice *curr;
- port = &s->port;
- curr = port->dev;
-
- if (dev) {
- if (curr) {
- usb_attach(port, NULL);
- /* TODO: signal some interrupts */
- }
-
- musb_intr_set(s, musb_irq_vbus_request, 1);
-
- /* Send the attach message to device */
- usb_send_msg(dev, USB_MSG_ATTACH);
- } else if (curr) {
- /* Send the detach message */
- usb_send_msg(curr, USB_MSG_DETACH);
-
- musb_intr_set(s, musb_irq_disconnect, 1);
- }
+ musb_intr_set(s, musb_irq_vbus_request, 1);
+ musb_session_update(s, 0, s->session);
+}
- port->dev = dev;
+static void musb_detach(USBPort *port)
+{
+ MUSBState *s = (MUSBState *) port->opaque;
- musb_session_update(s, !!curr, s->session);
+ musb_intr_set(s, musb_irq_disconnect, 1);
+ musb_session_update(s, 1, s->session);
}
static inline void musb_cb_tick0(void *opaque)
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 7b13bdd..c859540 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -322,52 +322,46 @@ static inline void ohci_set_interrupt(OHCIState *ohci, uint32_t intr)
}
/* Attach or detach a device on a root hub port. */
-static void ohci_attach(USBPort *port1, USBDevice *dev)
+static void ohci_attach(USBPort *port1)
{
OHCIState *s = port1->opaque;
OHCIPort *port = &s->rhport[port1->index];
- uint32_t old_state = port->ctrl;
- if (dev) {
- if (port->port.dev) {
- usb_attach(port1, NULL);
- }
- /* set connect status */
- port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
-
- /* update speed */
- if (dev->speed == USB_SPEED_LOW)
- port->ctrl |= OHCI_PORT_LSDA;
- else
- port->ctrl &= ~OHCI_PORT_LSDA;
- port->port.dev = dev;
-
- /* notify of remote-wakeup */
- if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND)
- ohci_set_interrupt(s, OHCI_INTR_RD);
-
- /* send the attach message */
- usb_send_msg(dev, USB_MSG_ATTACH);
- DPRINTF("usb-ohci: Attached port %d\n", port1->index);
+ /* set connect status */
+ port->ctrl |= OHCI_PORT_CCS | OHCI_PORT_CSC;
+
+ /* update speed */
+ if (port->port.dev->speed == USB_SPEED_LOW) {
+ port->ctrl |= OHCI_PORT_LSDA;
} else {
- /* set connect status */
- if (port->ctrl & OHCI_PORT_CCS) {
- port->ctrl &= ~OHCI_PORT_CCS;
- port->ctrl |= OHCI_PORT_CSC;
- }
- /* disable port */
- if (port->ctrl & OHCI_PORT_PES) {
- port->ctrl &= ~OHCI_PORT_PES;
- port->ctrl |= OHCI_PORT_PESC;
- }
- dev = port->port.dev;
- if (dev) {
- /* send the detach message */
- usb_send_msg(dev, USB_MSG_DETACH);
- }
- port->port.dev = NULL;
- DPRINTF("usb-ohci: Detached port %d\n", port1->index);
+ port->ctrl &= ~OHCI_PORT_LSDA;
+ }
+
+ /* notify of remote-wakeup */
+ if ((s->ctl & OHCI_CTL_HCFS) == OHCI_USB_SUSPEND) {
+ ohci_set_interrupt(s, OHCI_INTR_RD);
+ }
+
+ DPRINTF("usb-ohci: Attached port %d\n", port1->index);
+}
+
+static void ohci_detach(USBPort *port1)
+{
+ OHCIState *s = port1->opaque;
+ OHCIPort *port = &s->rhport[port1->index];
+ uint32_t old_state = port->ctrl;
+
+ /* set connect status */
+ if (port->ctrl & OHCI_PORT_CCS) {
+ port->ctrl &= ~OHCI_PORT_CCS;
+ port->ctrl |= OHCI_PORT_CSC;
+ }
+ /* disable port */
+ if (port->ctrl & OHCI_PORT_PES) {
+ port->ctrl &= ~OHCI_PORT_PES;
+ port->ctrl |= OHCI_PORT_PESC;
}
+ DPRINTF("usb-ohci: Detached port %d\n", port1->index);
if (old_state != port->ctrl)
ohci_set_interrupt(s, OHCI_INTR_RHSC);
@@ -413,8 +407,9 @@ static void ohci_reset(void *opaque)
{
port = &ohci->rhport[i];
port->ctrl = 0;
- if (port->port.dev)
- ohci_attach(&port->port, port->port.dev);
+ if (port->port.dev) {
+ usb_attach(&port->port, port->port.dev);
+ }
}
if (ohci->async_td) {
usb_cancel_packet(&ohci->usb_packet);
@@ -1671,6 +1666,7 @@ static CPUWriteMemoryFunc * const ohci_writefn[3]={
static USBPortOps ohci_port_ops = {
.attach = ohci_attach,
+ .detach = ohci_detach,
};
static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index 0f9ef1e..5e2e34a 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -307,8 +307,6 @@ static UHCIAsync *uhci_async_find_td(UHCIState *s, uint32_t addr, uint32_t token
return match;
}
-static void uhci_attach(USBPort *port1, USBDevice *dev);
-
static void uhci_update_irq(UHCIState *s)
{
int level;
@@ -348,8 +346,9 @@ static void uhci_reset(void *opaque)
for(i = 0; i < NB_PORTS; i++) {
port = &s->ports[i];
port->ctrl = 0x0080;
- if (port->port.dev)
- uhci_attach(&port->port, port->port.dev);
+ if (port->port.dev) {
+ usb_attach(&port->port, port->port.dev);
+ }
}
uhci_async_cancel_all(s);
@@ -593,50 +592,41 @@ static void uhci_resume (void *opaque)
}
}
-static void uhci_attach(USBPort *port1, USBDevice *dev)
+static void uhci_attach(USBPort *port1)
{
UHCIState *s = port1->opaque;
UHCIPort *port = &s->ports[port1->index];
- if (dev) {
- if (port->port.dev) {
- usb_attach(port1, NULL);
- }
- /* set connect status */
- port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
+ /* set connect status */
+ port->ctrl |= UHCI_PORT_CCS | UHCI_PORT_CSC;
- /* update speed */
- if (dev->speed == USB_SPEED_LOW)
- port->ctrl |= UHCI_PORT_LSDA;
- else
- port->ctrl &= ~UHCI_PORT_LSDA;
-
- uhci_resume(s);
-
- port->port.dev = dev;
- /* send the attach message */
- usb_send_msg(dev, USB_MSG_ATTACH);
+ /* update speed */
+ if (port->port.dev->speed == USB_SPEED_LOW) {
+ port->ctrl |= UHCI_PORT_LSDA;
} else {
- /* set connect status */
- if (port->ctrl & UHCI_PORT_CCS) {
- port->ctrl &= ~UHCI_PORT_CCS;
- port->ctrl |= UHCI_PORT_CSC;
- }
- /* disable port */
- if (port->ctrl & UHCI_PORT_EN) {
- port->ctrl &= ~UHCI_PORT_EN;
- port->ctrl |= UHCI_PORT_ENC;
- }
+ port->ctrl &= ~UHCI_PORT_LSDA;
+ }
- uhci_resume(s);
+ uhci_resume(s);
+}
- dev = port->port.dev;
- if (dev) {
- /* send the detach message */
- usb_send_msg(dev, USB_MSG_DETACH);
- }
- port->port.dev = NULL;
+static void uhci_detach(USBPort *port1)
+{
+ UHCIState *s = port1->opaque;
+ UHCIPort *port = &s->ports[port1->index];
+
+ /* set connect status */
+ if (port->ctrl & UHCI_PORT_CCS) {
+ port->ctrl &= ~UHCI_PORT_CCS;
+ port->ctrl |= UHCI_PORT_CSC;
}
+ /* disable port */
+ if (port->ctrl & UHCI_PORT_EN) {
+ port->ctrl &= ~UHCI_PORT_EN;
+ port->ctrl |= UHCI_PORT_ENC;
+ }
+
+ uhci_resume(s);
}
static int uhci_broadcast_packet(UHCIState *s, USBPacket *p)
@@ -1103,6 +1093,7 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
static USBPortOps uhci_port_ops = {
.attach = uhci_attach,
+ .detach = uhci_detach,
};
static int usb_uhci_common_initfn(UHCIState *s)
diff --git a/hw/usb.c b/hw/usb.c
index 39d29f3..2eda86a 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -28,7 +28,25 @@
void usb_attach(USBPort *port, USBDevice *dev)
{
- port->ops->attach(port, dev);
+ if (dev != NULL) {
+ /* attach */
+ if (port->dev) {
+ usb_attach(port, NULL);
+ }
+ dev->port = port;
+ port->dev = dev;
+ port->ops->attach(port);
+ usb_send_msg(dev, USB_MSG_ATTACH);
+ } else {
+ /* detach */
+ dev = port->dev;
+ port->ops->detach(port);
+ if (dev) {
+ usb_send_msg(dev, USB_MSG_DETACH);
+ dev->port = NULL;
+ port->dev = NULL;
+ }
+ }
}
/**********************/
diff --git a/hw/usb.h b/hw/usb.h
index 218788f..3744d19 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -147,6 +147,7 @@ struct USBDescString {
struct USBDevice {
DeviceState qdev;
USBDeviceInfo *info;
+ USBPort *port;
void *opaque;
int speed;
@@ -217,7 +218,8 @@ struct USBDeviceInfo {
};
typedef struct USBPortOps {
- void (*attach)(USBPort *port, USBDevice *dev);
+ void (*attach)(USBPort *port);
+ void (*detach)(USBPort *port);
} USBPortOps;
/* USB port on which a device can be connected */
commit 0d86d2bebb625a222f70b76972139f6a272e3e0b
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Dec 1 11:08:44 2010 +0100
usb: create USBPortOps, move attach there.
Create USBPortOps struct, move the attach function to that struct.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index af537c2..9dc8793 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -113,12 +113,14 @@ USBDevice *usb_create_simple(USBBus *bus, const char *name)
}
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
- USBDevice *pdev, usb_attachfn attach)
+ USBDevice *pdev, USBPortOps *ops)
{
port->opaque = opaque;
port->index = index;
- port->attach = attach;
port->pdev = pdev;
+ port->opaque = opaque;
+ port->index = index;
+ port->ops = ops;
QTAILQ_INSERT_TAIL(&bus->free, port, next);
bus->nfree++;
}
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 3c7c3ee..b3d7298 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -506,6 +506,10 @@ static void usb_hub_handle_destroy(USBDevice *dev)
}
}
+static USBPortOps usb_hub_port_ops = {
+ .attach = usb_hub_attach,
+};
+
static int usb_hub_initfn(USBDevice *dev)
{
USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
@@ -516,7 +520,7 @@ static int usb_hub_initfn(USBDevice *dev)
for (i = 0; i < NUM_PORTS; i++) {
port = &s->ports[i];
usb_register_port(usb_bus_from_device(dev),
- &port->port, s, i, &s->dev, usb_hub_attach);
+ &port->port, s, i, &s->dev, &usb_hub_port_ops);
port->wPortStatus = PORT_STAT_POWER;
port->wPortChange = 0;
}
diff --git a/hw/usb-musb.c b/hw/usb-musb.c
index 9efe7a6..592d3e6 100644
--- a/hw/usb-musb.c
+++ b/hw/usb-musb.c
@@ -261,6 +261,10 @@
static void musb_attach(USBPort *port, USBDevice *dev);
+static USBPortOps musb_port_ops = {
+ .attach = musb_attach,
+};
+
typedef struct {
uint16_t faddr[2];
uint8_t haddr[2];
@@ -343,7 +347,7 @@ struct MUSBState {
}
usb_bus_new(&s->bus, NULL /* FIXME */);
- usb_register_port(&s->bus, &s->port, s, 0, NULL, musb_attach);
+ usb_register_port(&s->bus, &s->port, s, 0, NULL, &musb_port_ops);
return s;
}
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 240e840..7b13bdd 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1669,6 +1669,10 @@ static CPUWriteMemoryFunc * const ohci_writefn[3]={
ohci_mem_write
};
+static USBPortOps ohci_port_ops = {
+ .attach = ohci_attach,
+};
+
static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
int num_ports, uint32_t localmem_base)
{
@@ -1699,7 +1703,7 @@ static void usb_ohci_init(OHCIState *ohci, DeviceState *dev,
usb_bus_new(&ohci->bus, dev);
ohci->num_ports = num_ports;
for (i = 0; i < num_ports; i++) {
- usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, NULL, ohci_attach);
+ usb_register_port(&ohci->bus, &ohci->rhport[i].port, ohci, i, NULL, &ohci_port_ops);
}
ohci->async_td = 0;
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index b9b822f..0f9ef1e 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1101,6 +1101,10 @@ static void uhci_map(PCIDevice *pci_dev, int region_num,
register_ioport_read(addr, 32, 1, uhci_ioport_readb, s);
}
+static USBPortOps uhci_port_ops = {
+ .attach = uhci_attach,
+};
+
static int usb_uhci_common_initfn(UHCIState *s)
{
uint8_t *pci_conf = s->dev.config;
@@ -1115,7 +1119,7 @@ static int usb_uhci_common_initfn(UHCIState *s)
usb_bus_new(&s->bus, &s->dev.qdev);
for(i = 0; i < NB_PORTS; i++) {
- usb_register_port(&s->bus, &s->ports[i].port, s, i, NULL, uhci_attach);
+ usb_register_port(&s->bus, &s->ports[i].port, s, i, NULL, &uhci_port_ops);
}
s->frame_timer = qemu_new_timer(vm_clock, uhci_frame_timer, s);
s->expire_time = qemu_get_clock(vm_clock) +
diff --git a/hw/usb.c b/hw/usb.c
index a326bcf..39d29f3 100644
--- a/hw/usb.c
+++ b/hw/usb.c
@@ -28,7 +28,7 @@
void usb_attach(USBPort *port, USBDevice *dev)
{
- port->attach(port, dev);
+ port->ops->attach(port, dev);
}
/**********************/
diff --git a/hw/usb.h b/hw/usb.h
index 966d47e..218788f 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -216,12 +216,14 @@ struct USBDeviceInfo {
USBDevice *(*usbdevice_init)(const char *params);
};
-typedef void (*usb_attachfn)(USBPort *port, USBDevice *dev);
+typedef struct USBPortOps {
+ void (*attach)(USBPort *port, USBDevice *dev);
+} USBPortOps;
/* USB port on which a device can be connected */
struct USBPort {
USBDevice *dev;
- usb_attachfn attach;
+ USBPortOps *ops;
void *opaque;
USBDevice *pdev;
int index; /* internal port index, may be used with the opaque */
@@ -333,7 +335,7 @@ USBDevice *usb_create(USBBus *bus, const char *name);
USBDevice *usb_create_simple(USBBus *bus, const char *name);
USBDevice *usbdevice_create(const char *cmdline);
void usb_register_port(USBBus *bus, USBPort *port, void *opaque, int index,
- USBDevice *pdev, usb_attachfn attach);
+ USBDevice *pdev, USBPortOps *ops);
void usb_unregister_port(USBBus *bus, USBPort *port);
int usb_device_attach(USBDevice *dev);
int usb_device_detach(USBDevice *dev);
commit b36e391441906c36ed0856b69de84001860402bf
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Tue Jan 11 14:10:15 2011 +0200
ioeventfd: error handling cleanup
- Don't return status from start/stop functions where it's ignored
- report errors to make debugging easier
- assert on unexpected failures
- don't disable notifiers on error so that we'll
retry when guest driver restarts
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
Acked-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 70c40ee..d07ff97 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -195,12 +195,16 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
if (assign) {
r = event_notifier_init(notifier, 1);
if (r < 0) {
+ error_report("%s: unable to init event notifier: %d",
+ __func__, r);
return r;
}
r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
n, assign);
if (r < 0) {
+ error_report("%s: unable to map ioeventfd: %d",
+ __func__, r);
event_notifier_cleanup(notifier);
}
} else {
@@ -208,6 +212,8 @@ static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
n, assign);
if (r < 0) {
+ error_report("%s: unable to unmap ioeventfd: %d",
+ __func__, r);
return r;
}
@@ -246,14 +252,14 @@ static void virtio_pci_set_host_notifier_fd_handler(VirtIOPCIProxy *proxy,
}
}
-static int virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
+static void virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
{
int n, r;
if (!(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) ||
proxy->ioeventfd_disabled ||
proxy->ioeventfd_started) {
- return 0;
+ return;
}
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
@@ -269,7 +275,7 @@ static int virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
virtio_pci_set_host_notifier_fd_handler(proxy, n, true);
}
proxy->ioeventfd_started = true;
- return 0;
+ return;
assign_error:
while (--n >= 0) {
@@ -278,19 +284,20 @@ assign_error:
}
virtio_pci_set_host_notifier_fd_handler(proxy, n, false);
- virtio_pci_set_host_notifier_internal(proxy, n, false);
+ r = virtio_pci_set_host_notifier_internal(proxy, n, false);
+ assert(r >= 0);
}
proxy->ioeventfd_started = false;
- proxy->ioeventfd_disabled = true;
- return r;
+ error_report("%s: failed. Fallback to a userspace (slower).", __func__);
}
-static int virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
+static void virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
{
+ int r;
int n;
if (!proxy->ioeventfd_started) {
- return 0;
+ return;
}
for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
@@ -299,10 +306,10 @@ static int virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
}
virtio_pci_set_host_notifier_fd_handler(proxy, n, false);
- virtio_pci_set_host_notifier_internal(proxy, n, false);
+ r = virtio_pci_set_host_notifier_internal(proxy, n, false);
+ assert(r >= 0);
}
proxy->ioeventfd_started = false;
- return 0;
}
static void virtio_pci_reset(DeviceState *d)
@@ -706,7 +713,6 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
proxy->host_features = vdev->get_features(vdev, proxy->host_features);
-
}
static int virtio_blk_init_pci(PCIDevice *pci_dev)
commit ed5a83ddd8c1d8ec7b1015315530cf29949e7c48
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Tue Nov 30 17:35:34 2010 +0100
usb: move remote wakeup handling to common code
This patch moves setting and clearing the remote_wakeup feature
bit (via USB_REQ_{SET,CLEAR}_FEATURE) to common code. Also
USB_REQ_GET_STATUS handling is moved to common code.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index 36c90a3..22e6845 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -396,33 +396,18 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
ret = 0;
switch (request) {
- case DeviceRequest | USB_REQ_GET_STATUS:
case InterfaceRequest | USB_REQ_GET_STATUS:
case EndpointRequest | USB_REQ_GET_STATUS:
- data[0] = (1 << USB_DEVICE_SELF_POWERED) |
- (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
+ data[0] = 0x00;
data[1] = 0x00;
ret = 2;
break;
- case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
case InterfaceOutRequest | USB_REQ_CLEAR_FEATURE:
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 0;
- } else {
- goto fail;
- }
- ret = 0;
- break;
- case DeviceOutRequest | USB_REQ_SET_FEATURE:
+ goto fail;
case InterfaceOutRequest | USB_REQ_SET_FEATURE:
case EndpointOutRequest | USB_REQ_SET_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 1;
- } else {
- goto fail;
- }
- ret = 0;
+ goto fail;
break;
case InterfaceRequest | USB_REQ_GET_INTERFACE:
if (value != 0 || (index & ~1) || length != 1)
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index 14c9e11..56ef734 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -299,6 +299,32 @@ int usb_desc_handle_control(USBDevice *dev, int request, int value,
}
trace_usb_set_config(dev->addr, value, ret);
break;
+
+ case DeviceRequest | USB_REQ_GET_STATUS:
+ data[0] = 0;
+ if (dev->config->bmAttributes & 0x40) {
+ data[0] |= 1 << USB_DEVICE_SELF_POWERED;
+ }
+ if (dev->remote_wakeup) {
+ data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
+ }
+ data[1] = 0x00;
+ ret = 2;
+ break;
+ case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
+ if (value == USB_DEVICE_REMOTE_WAKEUP) {
+ dev->remote_wakeup = 0;
+ ret = 0;
+ }
+ trace_usb_clear_device_feature(dev->addr, value, ret);
+ break;
+ case DeviceOutRequest | USB_REQ_SET_FEATURE:
+ if (value == USB_DEVICE_REMOTE_WAKEUP) {
+ dev->remote_wakeup = 1;
+ ret = 0;
+ }
+ trace_usb_set_device_feature(dev->addr, value, ret);
+ break;
}
return ret;
}
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 21c0c72..1c35960 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -673,28 +673,6 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
ret = 0;
switch(request) {
- case DeviceRequest | USB_REQ_GET_STATUS:
- data[0] = (1 << USB_DEVICE_SELF_POWERED) |
- (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
- data[1] = 0x00;
- ret = 2;
- break;
- case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 0;
- } else {
- goto fail;
- }
- ret = 0;
- break;
- case DeviceOutRequest | USB_REQ_SET_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 1;
- } else {
- goto fail;
- }
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index fc0b94b..3c7c3ee 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -269,34 +269,12 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
}
switch(request) {
- case DeviceRequest | USB_REQ_GET_STATUS:
- data[0] = (1 << USB_DEVICE_SELF_POWERED) |
- (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
- data[1] = 0x00;
- ret = 2;
- break;
- case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 0;
- } else {
- goto fail;
- }
- ret = 0;
- break;
case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
if (value == 0 && index != 0x81) { /* clear ep halt */
goto fail;
}
ret = 0;
break;
- case DeviceOutRequest | USB_REQ_SET_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 1;
- } else {
- goto fail;
- }
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 56c6f3d..74e657e 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -239,28 +239,6 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
ret = 0;
switch (request) {
- case DeviceRequest | USB_REQ_GET_STATUS:
- data[0] = (1 << USB_DEVICE_SELF_POWERED) |
- (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
- data[1] = 0x00;
- ret = 2;
- break;
- case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 0;
- } else {
- goto fail;
- }
- ret = 0;
- break;
- case DeviceOutRequest | USB_REQ_SET_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 1;
- } else {
- goto fail;
- }
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
@@ -285,7 +263,6 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
ret = 1;
break;
default:
- fail:
ret = USB_RET_STALL;
break;
}
diff --git a/hw/usb-net.c b/hw/usb-net.c
index f123045..bf51bb3 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1055,31 +1055,6 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
ret = 0;
switch(request) {
- case DeviceRequest | USB_REQ_GET_STATUS:
- data[0] = (1 << USB_DEVICE_SELF_POWERED) |
- (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
- data[1] = 0x00;
- ret = 2;
- break;
-
- case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 0;
- } else {
- goto fail;
- }
- ret = 0;
- break;
-
- case DeviceOutRequest | USB_REQ_SET_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 1;
- } else {
- goto fail;
- }
- ret = 0;
- break;
-
case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
if (!is_rndis(s) || value || index != 0) {
goto fail;
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 2bdb10b..6763d52 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -232,28 +232,6 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
ret = 0;
switch (request) {
- case DeviceRequest | USB_REQ_GET_STATUS:
- data[0] = (0 << USB_DEVICE_SELF_POWERED) |
- (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
- data[1] = 0x00;
- ret = 2;
- break;
- case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 0;
- } else {
- goto fail;
- }
- ret = 0;
- break;
- case DeviceOutRequest | USB_REQ_SET_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 1;
- } else {
- goto fail;
- }
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index 3a98e80..16be7a2 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -262,28 +262,6 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
ret = 0;
switch (request) {
- case DeviceRequest | USB_REQ_GET_STATUS:
- data[0] = (1 << USB_DEVICE_SELF_POWERED) |
- (dev->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP);
- data[1] = 0x00;
- ret = 2;
- break;
- case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 0;
- } else {
- goto fail;
- }
- ret = 0;
- break;
- case DeviceOutRequest | USB_REQ_SET_FEATURE:
- if (value == USB_DEVICE_REMOTE_WAKEUP) {
- dev->remote_wakeup = 1;
- } else {
- goto fail;
- }
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
@@ -320,7 +298,6 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
ret = 0;
break;
default:
- fail:
ret = USB_RET_STALL;
break;
}
diff --git a/trace-events b/trace-events
index 9ef8474..45e7582 100644
--- a/trace-events
+++ b/trace-events
@@ -196,6 +196,8 @@ disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query con
disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
disable usb_set_addr(int addr) "dev %d"
disable usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d"
+disable usb_clear_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d"
+disable usb_set_device_feature(int addr, int feature, int ret) "dev %d, feature %d, ret %d"
# vl.c
disable vm_state_notify(int running, int reason) "running %d reason %d"
commit a980a065fb5e86d6dec337e6cb6ff432f1a143c9
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Nov 26 20:20:41 2010 +0100
usb: move USB_REQ_{GET,SET}_CONFIGURATION handling to common code
This patch adds fields to the USBDevice struct for the current
speed (hard-wired to full speed for now) and current device
configuration. Also a init function is added which inializes
these fields. This allows USB_REQ_{GET,SET}_CONFIGURATION
handling to be moved to common code.
For most drivers the conversion is trivial ad they support a single
configuration only anyway. One exception is bluetooth where some
device-specific setup code runs after get/set configuration. The
other is usb-net which actually has two configurations so the
the code to check for the active configuration has been adapted.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index c0bfc35..36c90a3 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -380,6 +380,17 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
ret = usb_desc_handle_control(dev, request, value, index, length, data);
if (ret >= 0) {
+ switch (request) {
+ case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+ s->config = 0;
+ break;
+ case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+ s->config = 1;
+ usb_bt_fifo_reset(&s->evt);
+ usb_bt_fifo_reset(&s->acl);
+ usb_bt_fifo_reset(&s->sco);
+ break;
+ }
return ret;
}
@@ -413,23 +424,6 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
- case DeviceRequest | USB_REQ_GET_CONFIGURATION:
- data[0] = 1;
- ret = 1;
- s->config = 0;
- break;
- case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
- ret = 0;
- if (value != 1 && value != 0) {
- printf("%s: Wrong SET_CONFIGURATION request (%i)\n",
- __FUNCTION__, value);
- goto fail;
- }
- s->config = 1;
- usb_bt_fifo_reset(&s->evt);
- usb_bt_fifo_reset(&s->acl);
- usb_bt_fifo_reset(&s->sco);
- break;
case InterfaceRequest | USB_REQ_GET_INTERFACE:
if (value != 0 || (index & ~1) || length != 1)
goto fail;
@@ -544,8 +538,7 @@ static void usb_bt_handle_destroy(USBDevice *dev)
static int usb_bt_initfn(USBDevice *dev)
{
- struct USBBtState *s = DO_UPCAST(struct USBBtState, dev, dev);
- s->dev.speed = USB_SPEED_HIGH;
+ usb_desc_init(dev);
return 0;
}
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index 3e87f46..14c9e11 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -153,6 +153,16 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
/* ------------------------------------------------------------------ */
+void usb_desc_init(USBDevice *dev)
+{
+ const USBDesc *desc = dev->info->usb_desc;
+
+ assert(desc != NULL);
+ dev->speed = USB_SPEED_FULL;
+ dev->device = desc->full;
+ dev->config = dev->device->confs;
+}
+
void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
{
USBDescString *s;
@@ -230,12 +240,12 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
switch(type) {
case USB_DT_DEVICE:
- ret = usb_desc_device(&desc->id, desc->full, buf, sizeof(buf));
+ ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
trace_usb_desc_device(dev->addr, len, ret);
break;
case USB_DT_CONFIG:
- if (index < desc->full->bNumConfigurations) {
- ret = usb_desc_config(desc->full->confs + index, buf, sizeof(buf));
+ if (index < dev->device->bNumConfigurations) {
+ ret = usb_desc_config(dev->device->confs + index, buf, sizeof(buf));
}
trace_usb_desc_config(dev->addr, index, len, ret);
break;
@@ -262,7 +272,7 @@ int usb_desc_handle_control(USBDevice *dev, int request, int value,
int index, int length, uint8_t *data)
{
const USBDesc *desc = dev->info->usb_desc;
- int ret = -1;
+ int i, ret = -1;
assert(desc != NULL);
switch(request) {
@@ -275,6 +285,20 @@ int usb_desc_handle_control(USBDevice *dev, int request, int value,
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
ret = usb_desc_get_descriptor(dev, value, data, length);
break;
+
+ case DeviceRequest | USB_REQ_GET_CONFIGURATION:
+ data[0] = dev->config->bConfigurationValue;
+ ret = 1;
+ break;
+ case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
+ for (i = 0; i < dev->device->bNumConfigurations; i++) {
+ if (dev->device->confs[i].bConfigurationValue == value) {
+ dev->config = dev->device->confs + i;
+ ret = 0;
+ }
+ }
+ trace_usb_set_config(dev->addr, value, ret);
+ break;
}
return ret;
}
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
index 20fc400..d441725 100644
--- a/hw/usb-desc.h
+++ b/hw/usb-desc.h
@@ -78,6 +78,7 @@ int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
/* control message emulation helpers */
+void usb_desc_init(USBDevice *dev);
void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 72daddf..21c0c72 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -695,13 +695,6 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
- case DeviceRequest | USB_REQ_GET_CONFIGURATION:
- data[0] = 1;
- ret = 1;
- break;
- case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
@@ -822,7 +815,8 @@ static void usb_hid_handle_destroy(USBDevice *dev)
static int usb_hid_initfn(USBDevice *dev, int kind)
{
USBHIDState *s = DO_UPCAST(USBHIDState, dev, dev);
- s->dev.speed = USB_SPEED_FULL;
+
+ usb_desc_init(dev);
s->kind = kind;
if (s->kind == USB_MOUSE) {
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 1d321ac..fc0b94b 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -297,13 +297,6 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
- case DeviceRequest | USB_REQ_GET_CONFIGURATION:
- data[0] = 1;
- ret = 1;
- break;
- case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
@@ -541,7 +534,7 @@ static int usb_hub_initfn(USBDevice *dev)
USBHubPort *port;
int i;
- s->dev.speed = USB_SPEED_FULL;
+ usb_desc_init(dev);
for (i = 0; i < NUM_PORTS; i++) {
port = &s->ports[i];
usb_register_port(usb_bus_from_device(dev),
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index b54ccbc..56c6f3d 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -261,13 +261,6 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
- case DeviceRequest | USB_REQ_GET_CONFIGURATION:
- data[0] = 1;
- ret = 1;
- break;
- case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
@@ -502,7 +495,7 @@ static int usb_msd_initfn(USBDevice *dev)
usb_desc_set_string(dev, STR_SERIALNUMBER, dinfo->serial);
}
- s->dev.speed = USB_SPEED_FULL;
+ usb_desc_init(dev);
scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete);
s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0);
if (!s->scsi_dev) {
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 141d749..f123045 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -627,7 +627,6 @@ struct rndis_response {
typedef struct USBNetState {
USBDevice dev;
- unsigned int rndis;
enum rndis_state rndis_state;
uint32_t medium;
uint32_t speed;
@@ -648,6 +647,11 @@ typedef struct USBNetState {
QTAILQ_HEAD(rndis_resp_head, rndis_response) rndis_resp;
} USBNetState;
+static int is_rndis(USBNetState *s)
+{
+ return s->dev.config->bConfigurationValue == DEV_RNDIS_CONFIG_VALUE;
+}
+
static int ndis_query(USBNetState *s, uint32_t oid,
uint8_t *inbuf, unsigned int inlen, uint8_t *outbuf,
size_t outlen)
@@ -1077,8 +1081,9 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
break;
case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
- if (!s->rndis || value || index != 0)
+ if (!is_rndis(s) || value || index != 0) {
goto fail;
+ }
#ifdef TRAFFIC_DEBUG
{
unsigned int i;
@@ -1095,8 +1100,9 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
break;
case ClassInterfaceRequest | USB_CDC_GET_ENCAPSULATED_RESPONSE:
- if (!s->rndis || value || index != 0)
+ if (!is_rndis(s) || value || index != 0) {
goto fail;
+ }
ret = rndis_get_response(s, data);
if (!ret) {
data[0] = 0;
@@ -1116,27 +1122,6 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
#endif
break;
- case DeviceRequest | USB_REQ_GET_CONFIGURATION:
- data[0] = s->rndis ? DEV_RNDIS_CONFIG_VALUE : DEV_CONFIG_VALUE;
- ret = 1;
- break;
-
- case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
- switch (value & 0xff) {
- case DEV_CONFIG_VALUE:
- s->rndis = 0;
- break;
-
- case DEV_RNDIS_CONFIG_VALUE:
- s->rndis = 1;
- break;
-
- default:
- goto fail;
- }
- ret = 0;
- break;
-
case DeviceRequest | USB_REQ_GET_INTERFACE:
case InterfaceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
@@ -1207,7 +1192,7 @@ static int usb_net_handle_datain(USBNetState *s, USBPacket *p)
memcpy(p->data, &s->in_buf[s->in_ptr], ret);
s->in_ptr += ret;
if (s->in_ptr >= s->in_len &&
- (s->rndis || (s->in_len & (64 - 1)) || !ret)) {
+ (is_rndis(s) || (s->in_len & (64 - 1)) || !ret)) {
/* no short packet necessary */
s->in_ptr = s->in_len = 0;
}
@@ -1256,7 +1241,7 @@ static int usb_net_handle_dataout(USBNetState *s, USBPacket *p)
memcpy(&s->out_buf[s->out_ptr], p->data, sz);
s->out_ptr += sz;
- if (!s->rndis) {
+ if (!is_rndis(s)) {
if (ret < 64) {
qemu_send_packet(&s->nic->nc, s->out_buf, s->out_ptr);
s->out_ptr = 0;
@@ -1327,7 +1312,7 @@ static ssize_t usbnet_receive(VLANClientState *nc, const uint8_t *buf, size_t si
USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
struct rndis_packet_msg_type *msg;
- if (s->rndis) {
+ if (is_rndis(s)) {
msg = (struct rndis_packet_msg_type *) s->in_buf;
if (!s->rndis_state == RNDIS_DATA_INITIALIZED)
return -1;
@@ -1363,8 +1348,9 @@ static int usbnet_can_receive(VLANClientState *nc)
{
USBNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
- if (s->rndis && !s->rndis_state == RNDIS_DATA_INITIALIZED)
+ if (is_rndis(s) && !s->rndis_state == RNDIS_DATA_INITIALIZED) {
return 1;
+ }
return !s->in_len;
}
@@ -1397,9 +1383,8 @@ static int usb_net_initfn(USBDevice *dev)
{
USBNetState *s = DO_UPCAST(USBNetState, dev, dev);
- s->dev.speed = USB_SPEED_FULL;
+ usb_desc_init(dev);
- s->rndis = 1;
s->rndis_state = RNDIS_UNINITIALIZED;
QTAILQ_INIT(&s->rndis_resp);
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index c1f31c7..2bdb10b 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -254,13 +254,6 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
- case DeviceRequest | USB_REQ_GET_CONFIGURATION:
- data[0] = 1;
- ret = 1;
- break;
- case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
@@ -507,7 +500,8 @@ static void usb_serial_event(void *opaque, int event)
static int usb_serial_initfn(USBDevice *dev)
{
USBSerialState *s = DO_UPCAST(USBSerialState, dev, dev);
- s->dev.speed = USB_SPEED_FULL;
+
+ usb_desc_init(dev);
if (!s->cs) {
error_report("Property chardev is required");
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index ad1c3ae..3a98e80 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -284,13 +284,6 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
- case DeviceRequest | USB_REQ_GET_CONFIGURATION:
- data[0] = 1;
- ret = 1;
- break;
- case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_INTERFACE:
data[0] = 0;
ret = 1;
@@ -373,7 +366,7 @@ static void usb_wacom_handle_destroy(USBDevice *dev)
static int usb_wacom_initfn(USBDevice *dev)
{
USBWacomState *s = DO_UPCAST(USBWacomState, dev, dev);
- s->dev.speed = USB_SPEED_FULL;
+ usb_desc_init(dev);
s->changed = 1;
return 0;
}
diff --git a/hw/usb.h b/hw/usb.h
index 7b5c8df..966d47e 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -164,6 +164,8 @@ struct USBDevice {
int setup_index;
QLIST_HEAD(, USBDescString) strings;
+ const USBDescDevice *device;
+ const USBDescConfig *config;
};
struct USBDeviceInfo {
diff --git a/trace-events b/trace-events
index 7948c6c..9ef8474 100644
--- a/trace-events
+++ b/trace-events
@@ -195,6 +195,7 @@ disable usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d
disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
disable usb_set_addr(int addr) "dev %d"
+disable usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d"
# vl.c
disable vm_state_notify(int running, int reason) "running %d reason %d"
commit 41c6abbdeb5a86a135ee80a30541ecf52ffd3e23
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Nov 26 12:35:10 2010 +0100
usb: move USB_REQ_SET_ADDRESS handling to common code
USB_REQ_SET_ADDRESS handling is identical in *all* emulated devices.
Move it to common code.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index d7959ad..c0bfc35 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -413,10 +413,6 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
- case DeviceOutRequest | USB_REQ_SET_ADDRESS:
- dev->addr = value;
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index 69ab207..3e87f46 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -266,6 +266,12 @@ int usb_desc_handle_control(USBDevice *dev, int request, int value,
assert(desc != NULL);
switch(request) {
+ case DeviceOutRequest | USB_REQ_SET_ADDRESS:
+ dev->addr = value;
+ trace_usb_set_addr(dev->addr);
+ ret = 0;
+ break;
+
case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
ret = usb_desc_get_descriptor(dev, value, data, length);
break;
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 74d17fc..72daddf 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -695,10 +695,6 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
- case DeviceOutRequest | USB_REQ_SET_ADDRESS:
- dev->addr = value;
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 421d43d..1d321ac 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -297,10 +297,6 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
- case DeviceOutRequest | USB_REQ_SET_ADDRESS:
- dev->addr = value;
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 9aa8888..b54ccbc 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -261,10 +261,6 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
- case DeviceOutRequest | USB_REQ_SET_ADDRESS:
- dev->addr = value;
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
diff --git a/hw/usb-net.c b/hw/usb-net.c
index b2fe42e..141d749 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1076,11 +1076,6 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
ret = 0;
break;
- case DeviceOutRequest | USB_REQ_SET_ADDRESS:
- dev->addr = value;
- ret = 0;
- break;
-
case ClassInterfaceOutRequest | USB_CDC_SEND_ENCAPSULATED_COMMAND:
if (!s->rndis || value || index != 0)
goto fail;
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index f89eb9b..c1f31c7 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -254,10 +254,6 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
- case DeviceOutRequest | USB_REQ_SET_ADDRESS:
- dev->addr = value;
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index ffe6ac7..ad1c3ae 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -284,10 +284,6 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
}
ret = 0;
break;
- case DeviceOutRequest | USB_REQ_SET_ADDRESS:
- dev->addr = value;
- ret = 0;
- break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
diff --git a/trace-events b/trace-events
index 8264ff0..7948c6c 100644
--- a/trace-events
+++ b/trace-events
@@ -194,6 +194,7 @@ disable sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64""
disable usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
+disable usb_set_addr(int addr) "dev %d"
# vl.c
disable vm_state_notify(int running, int reason) "running %d reason %d"
commit 30c7d32a0a822a9496aee51e7269073311339ed9
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Nov 26 10:25:06 2010 +0100
usb network: use new descriptor infrastructure.
Switch the usb network driver over to the
new descriptor infrastructure.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 8492455..b2fe42e 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -25,6 +25,7 @@
#include "qemu-common.h"
#include "usb.h"
+#include "usb-desc.h"
#include "net.h"
#include "qemu-queue.h"
#include "sysemu.h"
@@ -89,182 +90,209 @@ enum usbstring_idx {
#define ETH_FRAME_LEN 1514 /* Max. octets in frame sans FCS */
-/*
- * mostly the same descriptor as the linux gadget rndis driver
- */
-static const uint8_t qemu_net_dev_descriptor[] = {
- 0x12, /* u8 bLength; */
- USB_DT_DEVICE, /* u8 bDescriptorType; Device */
- 0x00, 0x02, /* u16 bcdUSB; v2.0 */
- USB_CLASS_COMM, /* u8 bDeviceClass; */
- 0x00, /* u8 bDeviceSubClass; */
- 0x00, /* u8 bDeviceProtocol; [ low/full only ] */
- 0x40, /* u8 bMaxPacketSize0 */
- RNDIS_VENDOR_NUM & 0xff, RNDIS_VENDOR_NUM >> 8, /* u16 idVendor; */
- RNDIS_PRODUCT_NUM & 0xff, RNDIS_PRODUCT_NUM >> 8, /* u16 idProduct; */
- 0x00, 0x00, /* u16 bcdDevice */
- STRING_MANUFACTURER, /* u8 iManufacturer; */
- STRING_PRODUCT, /* u8 iProduct; */
- STRING_SERIALNUMBER, /* u8 iSerialNumber; */
- 0x02, /* u8 bNumConfigurations; */
+static const USBDescStrings usb_net_stringtable = {
+ [STRING_MANUFACTURER] = "QEMU",
+ [STRING_PRODUCT] = "RNDIS/QEMU USB Network Device",
+ [STRING_ETHADDR] = "400102030405",
+ [STRING_DATA] = "QEMU USB Net Data Interface",
+ [STRING_CONTROL] = "QEMU USB Net Control Interface",
+ [STRING_RNDIS_CONTROL] = "QEMU USB Net RNDIS Control Interface",
+ [STRING_CDC] = "QEMU USB Net CDC",
+ [STRING_SUBSET] = "QEMU USB Net Subset",
+ [STRING_RNDIS] = "QEMU USB Net RNDIS",
+ [STRING_SERIALNUMBER] = "1",
};
-static const uint8_t qemu_net_rndis_config_descriptor[] = {
- /* Configuration Descriptor */
- 0x09, /* u8 bLength */
- USB_DT_CONFIG, /* u8 bDescriptorType */
- 0x43, 0x00, /* le16 wTotalLength */
- 0x02, /* u8 bNumInterfaces */
- DEV_RNDIS_CONFIG_VALUE, /* u8 bConfigurationValue */
- STRING_RNDIS, /* u8 iConfiguration */
- 0xc0, /* u8 bmAttributes */
- 0x32, /* u8 bMaxPower */
- /* RNDIS Control Interface */
- 0x09, /* u8 bLength */
- USB_DT_INTERFACE, /* u8 bDescriptorType */
- 0x00, /* u8 bInterfaceNumber */
- 0x00, /* u8 bAlternateSetting */
- 0x01, /* u8 bNumEndpoints */
- USB_CLASS_COMM, /* u8 bInterfaceClass */
- USB_CDC_SUBCLASS_ACM, /* u8 bInterfaceSubClass */
- USB_CDC_ACM_PROTO_VENDOR, /* u8 bInterfaceProtocol */
- STRING_RNDIS_CONTROL, /* u8 iInterface */
- /* Header Descriptor */
- 0x05, /* u8 bLength */
- USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
- USB_CDC_HEADER_TYPE, /* u8 bDescriptorSubType */
- 0x10, 0x01, /* le16 bcdCDC */
- /* Call Management Descriptor */
- 0x05, /* u8 bLength */
- USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
- USB_CDC_CALL_MANAGEMENT_TYPE, /* u8 bDescriptorSubType */
- 0x00, /* u8 bmCapabilities */
- 0x01, /* u8 bDataInterface */
- /* ACM Descriptor */
- 0x04, /* u8 bLength */
- USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
- USB_CDC_ACM_TYPE, /* u8 bDescriptorSubType */
- 0x00, /* u8 bmCapabilities */
- /* Union Descriptor */
- 0x05, /* u8 bLength */
- USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
- USB_CDC_UNION_TYPE, /* u8 bDescriptorSubType */
- 0x00, /* u8 bMasterInterface0 */
- 0x01, /* u8 bSlaveInterface0 */
- /* Status Descriptor */
- 0x07, /* u8 bLength */
- USB_DT_ENDPOINT, /* u8 bDescriptorType */
- USB_DIR_IN | 1, /* u8 bEndpointAddress */
- USB_ENDPOINT_XFER_INT, /* u8 bmAttributes */
- STATUS_BYTECOUNT & 0xff, STATUS_BYTECOUNT >> 8, /* le16 wMaxPacketSize */
- 1 << LOG2_STATUS_INTERVAL_MSEC, /* u8 bInterval */
- /* RNDIS Data Interface */
- 0x09, /* u8 bLength */
- USB_DT_INTERFACE, /* u8 bDescriptorType */
- 0x01, /* u8 bInterfaceNumber */
- 0x00, /* u8 bAlternateSetting */
- 0x02, /* u8 bNumEndpoints */
- USB_CLASS_CDC_DATA, /* u8 bInterfaceClass */
- 0x00, /* u8 bInterfaceSubClass */
- 0x00, /* u8 bInterfaceProtocol */
- STRING_DATA, /* u8 iInterface */
- /* Source Endpoint */
- 0x07, /* u8 bLength */
- USB_DT_ENDPOINT, /* u8 bDescriptorType */
- USB_DIR_IN | 2, /* u8 bEndpointAddress */
- USB_ENDPOINT_XFER_BULK, /* u8 bmAttributes */
- 0x40, 0x00, /* le16 wMaxPacketSize */
- 0x00, /* u8 bInterval */
- /* Sink Endpoint */
- 0x07, /* u8 bLength */
- USB_DT_ENDPOINT, /* u8 bDescriptorType */
- USB_DIR_OUT | 2, /* u8 bEndpointAddress */
- USB_ENDPOINT_XFER_BULK, /* u8 bmAttributes */
- 0x40, 0x00, /* le16 wMaxPacketSize */
- 0x00 /* u8 bInterval */
+static const USBDescIface desc_iface_rndis[] = {
+ {
+ /* RNDIS Control Interface */
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
+ .bInterfaceProtocol = USB_CDC_ACM_PROTO_VENDOR,
+ .iInterface = STRING_RNDIS_CONTROL,
+ .ndesc = 4,
+ .descs = (USBDescOther[]) {
+ {
+ /* Header Descriptor */
+ .data = (uint8_t[]) {
+ 0x05, /* u8 bLength */
+ USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
+ USB_CDC_HEADER_TYPE, /* u8 bDescriptorSubType */
+ 0x10, 0x01, /* le16 bcdCDC */
+ },
+ },{
+ /* Call Management Descriptor */
+ .data = (uint8_t[]) {
+ 0x05, /* u8 bLength */
+ USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
+ USB_CDC_CALL_MANAGEMENT_TYPE, /* u8 bDescriptorSubType */
+ 0x00, /* u8 bmCapabilities */
+ 0x01, /* u8 bDataInterface */
+ },
+ },{
+ /* ACM Descriptor */
+ .data = (uint8_t[]) {
+ 0x04, /* u8 bLength */
+ USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
+ USB_CDC_ACM_TYPE, /* u8 bDescriptorSubType */
+ 0x00, /* u8 bmCapabilities */
+ },
+ },{
+ /* Union Descriptor */
+ .data = (uint8_t[]) {
+ 0x05, /* u8 bLength */
+ USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
+ USB_CDC_UNION_TYPE, /* u8 bDescriptorSubType */
+ 0x00, /* u8 bMasterInterface0 */
+ 0x01, /* u8 bSlaveInterface0 */
+ },
+ },
+ },
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | 0x01,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = STATUS_BYTECOUNT,
+ .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
+ },
+ }
+ },{
+ /* RNDIS Data Interface */
+ .bInterfaceNumber = 1,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+ .iInterface = STRING_DATA,
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | 0x02,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 0x40,
+ },{
+ .bEndpointAddress = USB_DIR_OUT | 0x02,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 0x40,
+ }
+ }
+ }
};
-static const uint8_t qemu_net_cdc_config_descriptor[] = {
- /* Configuration Descriptor */
- 0x09, /* u8 bLength */
- USB_DT_CONFIG, /* u8 bDescriptorType */
- 0x50, 0x00, /* le16 wTotalLength */
- 0x02, /* u8 bNumInterfaces */
- DEV_CONFIG_VALUE, /* u8 bConfigurationValue */
- STRING_CDC, /* u8 iConfiguration */
- 0xc0, /* u8 bmAttributes */
- 0x32, /* u8 bMaxPower */
- /* CDC Control Interface */
- 0x09, /* u8 bLength */
- USB_DT_INTERFACE, /* u8 bDescriptorType */
- 0x00, /* u8 bInterfaceNumber */
- 0x00, /* u8 bAlternateSetting */
- 0x01, /* u8 bNumEndpoints */
- USB_CLASS_COMM, /* u8 bInterfaceClass */
- USB_CDC_SUBCLASS_ETHERNET, /* u8 bInterfaceSubClass */
- USB_CDC_PROTO_NONE, /* u8 bInterfaceProtocol */
- STRING_CONTROL, /* u8 iInterface */
- /* Header Descriptor */
- 0x05, /* u8 bLength */
- USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
- USB_CDC_HEADER_TYPE, /* u8 bDescriptorSubType */
- 0x10, 0x01, /* le16 bcdCDC */
- /* Union Descriptor */
- 0x05, /* u8 bLength */
- USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
- USB_CDC_UNION_TYPE, /* u8 bDescriptorSubType */
- 0x00, /* u8 bMasterInterface0 */
- 0x01, /* u8 bSlaveInterface0 */
- /* Ethernet Descriptor */
- 0x0d, /* u8 bLength */
- USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
- USB_CDC_ETHERNET_TYPE, /* u8 bDescriptorSubType */
- STRING_ETHADDR, /* u8 iMACAddress */
- 0x00, 0x00, 0x00, 0x00, /* le32 bmEthernetStatistics */
- ETH_FRAME_LEN & 0xff, ETH_FRAME_LEN >> 8, /* le16 wMaxSegmentSize */
- 0x00, 0x00, /* le16 wNumberMCFilters */
- 0x00, /* u8 bNumberPowerFilters */
- /* Status Descriptor */
- 0x07, /* u8 bLength */
- USB_DT_ENDPOINT, /* u8 bDescriptorType */
- USB_DIR_IN | 1, /* u8 bEndpointAddress */
- USB_ENDPOINT_XFER_INT, /* u8 bmAttributes */
- STATUS_BYTECOUNT & 0xff, STATUS_BYTECOUNT >> 8, /* le16 wMaxPacketSize */
- 1 << LOG2_STATUS_INTERVAL_MSEC, /* u8 bInterval */
- /* CDC Data (nop) Interface */
- 0x09, /* u8 bLength */
- USB_DT_INTERFACE, /* u8 bDescriptorType */
- 0x01, /* u8 bInterfaceNumber */
- 0x00, /* u8 bAlternateSetting */
- 0x00, /* u8 bNumEndpoints */
- USB_CLASS_CDC_DATA, /* u8 bInterfaceClass */
- 0x00, /* u8 bInterfaceSubClass */
- 0x00, /* u8 bInterfaceProtocol */
- 0x00, /* u8 iInterface */
- /* CDC Data Interface */
- 0x09, /* u8 bLength */
- USB_DT_INTERFACE, /* u8 bDescriptorType */
- 0x01, /* u8 bInterfaceNumber */
- 0x01, /* u8 bAlternateSetting */
- 0x02, /* u8 bNumEndpoints */
- USB_CLASS_CDC_DATA, /* u8 bInterfaceClass */
- 0x00, /* u8 bInterfaceSubClass */
- 0x00, /* u8 bInterfaceProtocol */
- STRING_DATA, /* u8 iInterface */
- /* Source Endpoint */
- 0x07, /* u8 bLength */
- USB_DT_ENDPOINT, /* u8 bDescriptorType */
- USB_DIR_IN | 2, /* u8 bEndpointAddress */
- USB_ENDPOINT_XFER_BULK, /* u8 bmAttributes */
- 0x40, 0x00, /* le16 wMaxPacketSize */
- 0x00, /* u8 bInterval */
- /* Sink Endpoint */
- 0x07, /* u8 bLength */
- USB_DT_ENDPOINT, /* u8 bDescriptorType */
- USB_DIR_OUT | 2, /* u8 bEndpointAddress */
- USB_ENDPOINT_XFER_BULK, /* u8 bmAttributes */
- 0x40, 0x00, /* le16 wMaxPacketSize */
- 0x00 /* u8 bInterval */
+static const USBDescIface desc_iface_cdc[] = {
+ {
+ /* CDC Control Interface */
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET,
+ .bInterfaceProtocol = USB_CDC_PROTO_NONE,
+ .iInterface = STRING_CONTROL,
+ .ndesc = 3,
+ .descs = (USBDescOther[]) {
+ {
+ /* Header Descriptor */
+ .data = (uint8_t[]) {
+ 0x05, /* u8 bLength */
+ USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
+ USB_CDC_HEADER_TYPE, /* u8 bDescriptorSubType */
+ 0x10, 0x01, /* le16 bcdCDC */
+ },
+ },{
+ /* Union Descriptor */
+ .data = (uint8_t[]) {
+ 0x05, /* u8 bLength */
+ USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
+ USB_CDC_UNION_TYPE, /* u8 bDescriptorSubType */
+ 0x00, /* u8 bMasterInterface0 */
+ 0x01, /* u8 bSlaveInterface0 */
+ },
+ },{
+ /* Ethernet Descriptor */
+ .data = (uint8_t[]) {
+ 0x0d, /* u8 bLength */
+ USB_DT_CS_INTERFACE, /* u8 bDescriptorType */
+ USB_CDC_ETHERNET_TYPE, /* u8 bDescriptorSubType */
+ STRING_ETHADDR, /* u8 iMACAddress */
+ 0x00, 0x00, 0x00, 0x00, /* le32 bmEthernetStatistics */
+ ETH_FRAME_LEN & 0xff,
+ ETH_FRAME_LEN >> 8, /* le16 wMaxSegmentSize */
+ 0x00, 0x00, /* le16 wNumberMCFilters */
+ 0x00, /* u8 bNumberPowerFilters */
+ },
+ },
+ },
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | 0x01,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = STATUS_BYTECOUNT,
+ .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
+ },
+ }
+ },{
+ /* CDC Data Interface (off) */
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+ },{
+ /* CDC Data Interface */
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+ .iInterface = STRING_DATA,
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | 0x02,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 0x40,
+ },{
+ .bEndpointAddress = USB_DIR_OUT | 0x02,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 0x40,
+ }
+ }
+ }
+};
+
+static const USBDescDevice desc_device_net = {
+ .bcdUSB = 0x0200,
+ .bDeviceClass = USB_CLASS_COMM,
+ .bMaxPacketSize0 = 0x40,
+ .bNumConfigurations = 2,
+ .confs = (USBDescConfig[]) {
+ {
+ .bNumInterfaces = 2,
+ .bConfigurationValue = DEV_RNDIS_CONFIG_VALUE,
+ .iConfiguration = STRING_RNDIS,
+ .bmAttributes = 0xc0,
+ .bMaxPower = 0x32,
+ .nif = ARRAY_SIZE(desc_iface_rndis),
+ .ifs = desc_iface_rndis,
+ },{
+ .bNumInterfaces = 2,
+ .bConfigurationValue = DEV_CONFIG_VALUE,
+ .iConfiguration = STRING_CDC,
+ .bmAttributes = 0xc0,
+ .bMaxPower = 0x32,
+ .nif = ARRAY_SIZE(desc_iface_cdc),
+ .ifs = desc_iface_cdc,
+ }
+ },
+};
+
+static const USBDesc desc_net = {
+ .id = {
+ .idVendor = RNDIS_VENDOR_NUM,
+ .idProduct = RNDIS_PRODUCT_NUM,
+ .bcdDevice = 0,
+ .iManufacturer = STRING_MANUFACTURER,
+ .iProduct = STRING_PRODUCT,
+ .iSerialNumber = STRING_SERIALNUMBER,
+ },
+ .full = &desc_device_net,
+ .str = usb_net_stringtable,
};
/*
@@ -1010,25 +1038,18 @@ static void usb_net_handle_reset(USBDevice *dev)
{
}
-static const char * const usb_net_stringtable[] = {
- [STRING_MANUFACTURER] = "QEMU",
- [STRING_PRODUCT] = "RNDIS/QEMU USB Network Device",
- [STRING_ETHADDR] = "400102030405",
- [STRING_DATA] = "QEMU USB Net Data Interface",
- [STRING_CONTROL] = "QEMU USB Net Control Interface",
- [STRING_RNDIS_CONTROL] = "QEMU USB Net RNDIS Control Interface",
- [STRING_CDC] = "QEMU USB Net CDC",
- [STRING_SUBSET] = "QEMU USB Net Subset",
- [STRING_RNDIS] = "QEMU USB Net RNDIS",
- [STRING_SERIALNUMBER] = "1",
-};
-
static int usb_net_handle_control(USBDevice *dev, int request, int value,
int index, int length, uint8_t *data)
{
USBNetState *s = (USBNetState *) dev;
- int ret = 0;
+ int ret;
+ ret = usb_desc_handle_control(dev, request, value, index, length, data);
+ if (ret >= 0) {
+ return ret;
+ }
+
+ ret = 0;
switch(request) {
case DeviceRequest | USB_REQ_GET_STATUS:
data[0] = (1 << USB_DEVICE_SELF_POWERED) |
@@ -1100,64 +1121,6 @@ static int usb_net_handle_control(USBDevice *dev, int request, int value,
#endif
break;
- case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
- switch(value >> 8) {
- case USB_DT_DEVICE:
- ret = sizeof(qemu_net_dev_descriptor);
- memcpy(data, qemu_net_dev_descriptor, ret);
- break;
-
- case USB_DT_CONFIG:
- switch (value & 0xff) {
- case 0:
- ret = sizeof(qemu_net_rndis_config_descriptor);
- memcpy(data, qemu_net_rndis_config_descriptor, ret);
- break;
-
- case 1:
- ret = sizeof(qemu_net_cdc_config_descriptor);
- memcpy(data, qemu_net_cdc_config_descriptor, ret);
- break;
-
- default:
- goto fail;
- }
-
- data[2] = ret & 0xff;
- data[3] = ret >> 8;
- break;
-
- case USB_DT_STRING:
- switch (value & 0xff) {
- case 0:
- /* language ids */
- data[0] = 4;
- data[1] = 3;
- data[2] = 0x09;
- data[3] = 0x04;
- ret = 4;
- break;
-
- case STRING_ETHADDR:
- ret = set_usb_string(data, s->usbstring_mac);
- break;
-
- default:
- if (ARRAY_SIZE(usb_net_stringtable) > (value & 0xff)) {
- ret = set_usb_string(data,
- usb_net_stringtable[value & 0xff]);
- break;
- }
-
- goto fail;
- }
- break;
-
- default:
- goto fail;
- }
- break;
-
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = s->rndis ? DEV_RNDIS_CONFIG_VALUE : DEV_CONFIG_VALUE;
ret = 1;
@@ -1463,6 +1426,7 @@ static int usb_net_initfn(USBDevice *dev)
s->conf.macaddr.a[3],
s->conf.macaddr.a[4],
s->conf.macaddr.a[5]);
+ usb_desc_set_string(dev, STRING_ETHADDR, s->usbstring_mac);
add_boot_device_path(s->conf.bootindex, &dev->qdev, "/ethernet at 0");
return 0;
@@ -1500,6 +1464,7 @@ static struct USBDeviceInfo net_info = {
.qdev.name = "usb-net",
.qdev.fw_name = "network",
.qdev.size = sizeof(USBNetState),
+ .usb_desc = &desc_net,
.init = usb_net_initfn,
.handle_packet = usb_generic_handle_packet,
.handle_reset = usb_net_handle_reset,
commit 4a1e1bc416e99254dcc59a689b3806775ae8dabd
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Nov 26 12:26:17 2010 +0100
usb storage: serial number support
If a serial number is present for the drive fill it into the usb
serialnumber string descriptor.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 20ab886..9aa8888 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -482,6 +482,7 @@ static int usb_msd_initfn(USBDevice *dev)
{
MSDState *s = DO_UPCAST(MSDState, dev, dev);
BlockDriverState *bs = s->conf.bs;
+ DriveInfo *dinfo;
if (!bs) {
error_report("usb-msd: drive property not set");
@@ -500,6 +501,11 @@ static int usb_msd_initfn(USBDevice *dev)
bdrv_detach(bs, &s->dev.qdev);
s->conf.bs = NULL;
+ dinfo = drive_get_by_blockdev(bs);
+ if (dinfo && dinfo->serial) {
+ usb_desc_set_string(dev, STR_SERIALNUMBER, dinfo->serial);
+ }
+
s->dev.speed = USB_SPEED_FULL;
scsi_bus_new(&s->bus, &s->dev.qdev, 0, 1, usb_msd_command_complete);
s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0);
commit 132a3f55f05dff4eedde0d23d844ecdedef8ba68
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Nov 26 12:25:32 2010 +0100
usb descriptors: add settable strings.
This patch allows to set usb descriptor strings per device instance.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 8b4583c..af537c2 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -48,6 +48,7 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
pstrcpy(dev->product_desc, sizeof(dev->product_desc), info->product_desc);
dev->info = info;
dev->auto_attach = 1;
+ QLIST_INIT(&dev->strings);
rc = dev->info->init(dev);
if (rc == 0 && dev->auto_attach)
usb_device_attach(dev);
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
index 559ced7..69ab207 100644
--- a/hw/usb-desc.c
+++ b/hw/usb-desc.c
@@ -151,9 +151,42 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
return bLength;
}
-int usb_desc_string(const char* const *str, int index, uint8_t *dest, size_t len)
+/* ------------------------------------------------------------------ */
+
+void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
+{
+ USBDescString *s;
+
+ QLIST_FOREACH(s, &dev->strings, next) {
+ if (s->index == index) {
+ break;
+ }
+ }
+ if (s == NULL) {
+ s = qemu_mallocz(sizeof(*s));
+ s->index = index;
+ QLIST_INSERT_HEAD(&dev->strings, s, next);
+ }
+ qemu_free(s->str);
+ s->str = qemu_strdup(str);
+}
+
+const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
+{
+ USBDescString *s;
+
+ QLIST_FOREACH(s, &dev->strings, next) {
+ if (s->index == index) {
+ return s->str;
+ }
+ }
+ return NULL;
+}
+
+int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
{
uint8_t bLength, pos, i;
+ const char *str;
if (len < 4) {
return -1;
@@ -168,22 +201,25 @@ int usb_desc_string(const char* const *str, int index, uint8_t *dest, size_t len
return 4;
}
- if (str[index] == NULL) {
- return 0;
+ str = usb_desc_get_string(dev, index);
+ if (str == NULL) {
+ str = dev->info->usb_desc->str[index];
+ if (str == NULL) {
+ return 0;
+ }
}
- bLength = strlen(str[index]) * 2 + 2;
+
+ bLength = strlen(str) * 2 + 2;
dest[0] = bLength;
dest[1] = USB_DT_STRING;
i = 0; pos = 2;
while (pos+1 < bLength && pos+1 < len) {
- dest[pos++] = str[index][i++];
+ dest[pos++] = str[i++];
dest[pos++] = 0;
}
return pos;
}
-/* ------------------------------------------------------------------ */
-
int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
{
const USBDesc *desc = dev->info->usb_desc;
@@ -204,7 +240,7 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
trace_usb_desc_config(dev->addr, index, len, ret);
break;
case USB_DT_STRING:
- ret = usb_desc_string(desc->str, index, buf, sizeof(buf));
+ ret = usb_desc_string(dev, index, buf, sizeof(buf));
trace_usb_desc_string(dev->addr, index, len, ret);
break;
default:
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
index d80efdb..20fc400 100644
--- a/hw/usb-desc.h
+++ b/hw/usb-desc.h
@@ -76,9 +76,11 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len);
int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len);
int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
-int usb_desc_string(const char* const *str, int index, uint8_t *dest, size_t len);
/* control message emulation helpers */
+void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str);
+const char *usb_desc_get_string(USBDevice *dev, uint8_t index);
+int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len);
int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len);
int usb_desc_handle_control(USBDevice *dev, int request, int value,
int index, int length, uint8_t *data);
diff --git a/hw/usb.h b/hw/usb.h
index a29b6d6..7b5c8df 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -135,6 +135,13 @@ typedef struct USBDescConfig USBDescConfig;
typedef struct USBDescIface USBDescIface;
typedef struct USBDescEndpoint USBDescEndpoint;
typedef struct USBDescOther USBDescOther;
+typedef struct USBDescString USBDescString;
+
+struct USBDescString {
+ uint8_t index;
+ char *str;
+ QLIST_ENTRY(USBDescString) next;
+};
/* definition of a USB device */
struct USBDevice {
@@ -155,6 +162,8 @@ struct USBDevice {
int setup_state;
int setup_len;
int setup_index;
+
+ QLIST_HEAD(, USBDescString) strings;
};
struct USBDeviceInfo {
commit 062651c7e750a0c06a693d336c2b9edb893a2c94
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Nov 26 13:13:22 2010 +0100
usb hub: use new descriptor infrastructure.
Switch the usb hub driver over to the
new descriptor infrastructure.
It also removes the nr_ports variable and MAX_PORTS define and
introduces a NUM_PORTS define instead. The numver of ports was
(and still is) fixed at 8 anyway.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 8a3f829..421d43d 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -23,10 +23,11 @@
*/
#include "qemu-common.h"
#include "usb.h"
+#include "usb-desc.h"
//#define DEBUG
-#define MAX_PORTS 8
+#define NUM_PORTS 8
typedef struct USBHubPort {
USBPort port;
@@ -36,8 +37,7 @@ typedef struct USBHubPort {
typedef struct USBHubState {
USBDevice dev;
- int nb_ports;
- USBHubPort ports[MAX_PORTS];
+ USBHubPort ports[NUM_PORTS];
} USBHubState;
#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE)
@@ -83,6 +83,60 @@ typedef struct USBHubState {
/* same as Linux kernel root hubs */
+enum {
+ STR_MANUFACTURER = 1,
+ STR_PRODUCT,
+ STR_SERIALNUMBER,
+};
+
+static const USBDescStrings desc_strings = {
+ [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
+ [STR_PRODUCT] = "QEMU USB Hub",
+ [STR_SERIALNUMBER] = "314159",
+};
+
+static const USBDescIface desc_iface_hub = {
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_HUB,
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | 0x01,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 1 + (NUM_PORTS + 7) / 8,
+ .bInterval = 0xff,
+ },
+ }
+};
+
+static const USBDescDevice desc_device_hub = {
+ .bcdUSB = 0x0110,
+ .bDeviceClass = USB_CLASS_HUB,
+ .bMaxPacketSize0 = 8,
+ .bNumConfigurations = 1,
+ .confs = (USBDescConfig[]) {
+ {
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .bmAttributes = 0xe0,
+ .ifs = &desc_iface_hub,
+ },
+ },
+};
+
+static const USBDesc desc_hub = {
+ .id = {
+ .idVendor = 0,
+ .idProduct = 0,
+ .bcdDevice = 0x0101,
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT,
+ .iSerialNumber = STR_SERIALNUMBER,
+ },
+ .full = &desc_device_hub,
+ .str = desc_strings,
+};
+
static const uint8_t qemu_hub_dev_descriptor[] = {
0x12, /* u8 bLength; */
0x01, /* u8 bDescriptorType; Device */
@@ -209,6 +263,11 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
USBHubState *s = (USBHubState *)dev;
int ret;
+ ret = usb_desc_handle_control(dev, request, value, index, length, data);
+ if (ret >= 0) {
+ return ret;
+ }
+
switch(request) {
case DeviceRequest | USB_REQ_GET_STATUS:
data[0] = (1 << USB_DEVICE_SELF_POWERED) |
@@ -242,53 +301,6 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
dev->addr = value;
ret = 0;
break;
- case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
- switch(value >> 8) {
- case USB_DT_DEVICE:
- memcpy(data, qemu_hub_dev_descriptor,
- sizeof(qemu_hub_dev_descriptor));
- ret = sizeof(qemu_hub_dev_descriptor);
- break;
- case USB_DT_CONFIG:
- memcpy(data, qemu_hub_config_descriptor,
- sizeof(qemu_hub_config_descriptor));
-
- /* status change endpoint size based on number
- * of ports */
- data[22] = (s->nb_ports + 1 + 7) / 8;
-
- ret = sizeof(qemu_hub_config_descriptor);
- break;
- case USB_DT_STRING:
- switch(value & 0xff) {
- case 0:
- /* language ids */
- data[0] = 4;
- data[1] = 3;
- data[2] = 0x09;
- data[3] = 0x04;
- ret = 4;
- break;
- case 1:
- /* serial number */
- ret = set_usb_string(data, "314159");
- break;
- case 2:
- /* product description */
- ret = set_usb_string(data, "QEMU USB Hub");
- break;
- case 3:
- /* vendor description */
- ret = set_usb_string(data, "QEMU " QEMU_VERSION);
- break;
- default:
- goto fail;
- }
- break;
- default:
- goto fail;
- }
- break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
@@ -315,8 +327,9 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
{
unsigned int n = index - 1;
USBHubPort *port;
- if (n >= s->nb_ports)
+ if (n >= NUM_PORTS) {
goto fail;
+ }
port = &s->ports[n];
data[0] = port->wPortStatus;
data[1] = port->wPortStatus >> 8;
@@ -338,8 +351,9 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
unsigned int n = index - 1;
USBHubPort *port;
USBDevice *dev;
- if (n >= s->nb_ports)
+ if (n >= NUM_PORTS) {
goto fail;
+ }
port = &s->ports[n];
dev = port->port.dev;
switch(value) {
@@ -367,8 +381,9 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
unsigned int n = index - 1;
USBHubPort *port;
- if (n >= s->nb_ports)
+ if (n >= NUM_PORTS) {
goto fail;
+ }
port = &s->ports[n];
switch(value) {
case PORT_ENABLE:
@@ -403,17 +418,17 @@ static int usb_hub_handle_control(USBDevice *dev, int request, int value,
unsigned int n, limit, var_hub_size = 0;
memcpy(data, qemu_hub_hub_descriptor,
sizeof(qemu_hub_hub_descriptor));
- data[2] = s->nb_ports;
+ data[2] = NUM_PORTS;
/* fill DeviceRemovable bits */
- limit = ((s->nb_ports + 1 + 7) / 8) + 7;
+ limit = ((NUM_PORTS + 1 + 7) / 8) + 7;
for (n = 7; n < limit; n++) {
data[n] = 0x00;
var_hub_size++;
}
/* fill PortPwrCtrlMask bits */
- limit = limit + ((s->nb_ports + 7) / 8);
+ limit = limit + ((NUM_PORTS + 7) / 8);
for (;n < limit; n++) {
data[n] = 0xff;
var_hub_size++;
@@ -442,14 +457,14 @@ static int usb_hub_handle_data(USBDevice *dev, USBPacket *p)
USBHubPort *port;
unsigned int status;
int i, n;
- n = (s->nb_ports + 1 + 7) / 8;
+ n = (NUM_PORTS + 1 + 7) / 8;
if (p->len == 1) { /* FreeBSD workaround */
n = 1;
} else if (n > p->len) {
return USB_RET_BABBLE;
}
status = 0;
- for(i = 0; i < s->nb_ports; i++) {
+ for(i = 0; i < NUM_PORTS; i++) {
port = &s->ports[i];
if (port->wPortChange)
status |= (1 << (i + 1));
@@ -481,7 +496,7 @@ static int usb_hub_broadcast_packet(USBHubState *s, USBPacket *p)
USBDevice *dev;
int i, ret;
- for(i = 0; i < s->nb_ports; i++) {
+ for(i = 0; i < NUM_PORTS; i++) {
port = &s->ports[i];
dev = port->port.dev;
if (dev && (port->wPortStatus & PORT_STAT_ENABLE)) {
@@ -518,7 +533,7 @@ static void usb_hub_handle_destroy(USBDevice *dev)
USBHubState *s = (USBHubState *)dev;
int i;
- for (i = 0; i < s->nb_ports; i++) {
+ for (i = 0; i < NUM_PORTS; i++) {
usb_unregister_port(usb_bus_from_device(dev),
&s->ports[i].port);
}
@@ -530,9 +545,8 @@ static int usb_hub_initfn(USBDevice *dev)
USBHubPort *port;
int i;
- s->dev.speed = USB_SPEED_FULL,
- s->nb_ports = MAX_PORTS; /* FIXME: make configurable */
- for (i = 0; i < s->nb_ports; i++) {
+ s->dev.speed = USB_SPEED_FULL;
+ for (i = 0; i < NUM_PORTS; i++) {
port = &s->ports[i];
usb_register_port(usb_bus_from_device(dev),
&port->port, s, i, &s->dev, usb_hub_attach);
@@ -547,6 +561,7 @@ static struct USBDeviceInfo hub_info = {
.qdev.name = "usb-hub",
.qdev.fw_name = "hub",
.qdev.size = sizeof(USBHubState),
+ .usb_desc = &desc_hub,
.init = usb_hub_initfn,
.handle_packet = usb_hub_handle_packet,
.handle_reset = usb_hub_handle_reset,
commit 4696425cd05c7baa0a4b469d43ba4b8488bcfc0f
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Thu Nov 25 16:12:18 2010 +0100
usb bluetooth: use new descriptor infrastructure.
Switch the usb bluetooth driver over to the
new descriptor infrastructure.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index 56d1a6c..d7959ad 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -20,6 +20,7 @@
#include "qemu-common.h"
#include "usb.h"
+#include "usb-desc.h"
#include "net.h"
#include "bt.h"
@@ -51,251 +52,202 @@ struct USBBtState {
#define USB_ACL_EP 2
#define USB_SCO_EP 3
-static const uint8_t qemu_bt_dev_descriptor[] = {
- 0x12, /* u8 bLength; */
- USB_DT_DEVICE, /* u8 bDescriptorType; Device */
- 0x10, 0x01, /* u16 bcdUSB; v1.10 */
+enum {
+ STR_MANUFACTURER = 1,
+ STR_SERIALNUMBER,
+};
- 0xe0, /* u8 bDeviceClass; Wireless */
- 0x01, /* u8 bDeviceSubClass; Radio Frequency */
- 0x01, /* u8 bDeviceProtocol; Bluetooth */
- 0x40, /* u8 bMaxPacketSize0; 64 Bytes */
+static const USBDescStrings desc_strings = {
+ [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
+ [STR_SERIALNUMBER] = "1",
+};
- 0x12, 0x0a, /* u16 idVendor; */
- 0x01, 0x00, /* u16 idProduct; Bluetooth Dongle (HCI mode) */
- 0x58, 0x19, /* u16 bcdDevice; (some devices have 0x48, 0x02) */
+static const USBDescIface desc_iface_bluetooth[] = {
+ {
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 3,
+ .bInterfaceClass = 0xe0, /* Wireless */
+ .bInterfaceSubClass = 0x01, /* Radio Frequency */
+ .bInterfaceProtocol = 0x01, /* Bluetooth */
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | USB_EVT_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 0x10,
+ .bInterval = 0x02,
+ },
+ {
+ .bEndpointAddress = USB_DIR_OUT | USB_ACL_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 0x40,
+ .bInterval = 0x0a,
+ },
+ {
+ .bEndpointAddress = USB_DIR_IN | USB_ACL_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 0x40,
+ .bInterval = 0x0a,
+ },
+ },
+ },{
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = 0xe0, /* Wireless */
+ .bInterfaceSubClass = 0x01, /* Radio Frequency */
+ .bInterfaceProtocol = 0x01, /* Bluetooth */
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_OUT | USB_SCO_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 0,
+ .bInterval = 0x01,
+ },
+ {
+ .bEndpointAddress = USB_DIR_IN | USB_SCO_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 0,
+ .bInterval = 0x01,
+ },
+ },
+ },{
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = 0xe0, /* Wireless */
+ .bInterfaceSubClass = 0x01, /* Radio Frequency */
+ .bInterfaceProtocol = 0x01, /* Bluetooth */
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_OUT | USB_SCO_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 0x09,
+ .bInterval = 0x01,
+ },
+ {
+ .bEndpointAddress = USB_DIR_IN | USB_SCO_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 0x09,
+ .bInterval = 0x01,
+ },
+ },
+ },{
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 2,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = 0xe0, /* Wireless */
+ .bInterfaceSubClass = 0x01, /* Radio Frequency */
+ .bInterfaceProtocol = 0x01, /* Bluetooth */
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_OUT | USB_SCO_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 0x11,
+ .bInterval = 0x01,
+ },
+ {
+ .bEndpointAddress = USB_DIR_IN | USB_SCO_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 0x11,
+ .bInterval = 0x01,
+ },
+ },
+ },{
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 3,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = 0xe0, /* Wireless */
+ .bInterfaceSubClass = 0x01, /* Radio Frequency */
+ .bInterfaceProtocol = 0x01, /* Bluetooth */
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_OUT | USB_SCO_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 0x19,
+ .bInterval = 0x01,
+ },
+ {
+ .bEndpointAddress = USB_DIR_IN | USB_SCO_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 0x19,
+ .bInterval = 0x01,
+ },
+ },
+ },{
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 4,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = 0xe0, /* Wireless */
+ .bInterfaceSubClass = 0x01, /* Radio Frequency */
+ .bInterfaceProtocol = 0x01, /* Bluetooth */
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_OUT | USB_SCO_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 0x21,
+ .bInterval = 0x01,
+ },
+ {
+ .bEndpointAddress = USB_DIR_IN | USB_SCO_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 0x21,
+ .bInterval = 0x01,
+ },
+ },
+ },{
+ .bInterfaceNumber = 1,
+ .bAlternateSetting = 5,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = 0xe0, /* Wireless */
+ .bInterfaceSubClass = 0x01, /* Radio Frequency */
+ .bInterfaceProtocol = 0x01, /* Bluetooth */
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_OUT | USB_SCO_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 0x31,
+ .bInterval = 0x01,
+ },
+ {
+ .bEndpointAddress = USB_DIR_IN | USB_SCO_EP,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 0x31,
+ .bInterval = 0x01,
+ },
+ },
+ }
+};
- 0x00, /* u8 iManufacturer; */
- 0x00, /* u8 iProduct; */
- 0x00, /* u8 iSerialNumber; */
- 0x01, /* u8 bNumConfigurations; */
+static const USBDescDevice desc_device_bluetooth = {
+ .bcdUSB = 0x0110,
+ .bDeviceClass = 0xe0, /* Wireless */
+ .bDeviceSubClass = 0x01, /* Radio Frequency */
+ .bDeviceProtocol = 0x01, /* Bluetooth */
+ .bMaxPacketSize0 = 64,
+ .bNumConfigurations = 1,
+ .confs = (USBDescConfig[]) {
+ {
+ .bNumInterfaces = 2,
+ .bConfigurationValue = 1,
+ .bmAttributes = 0xc0,
+ .bMaxPower = 0,
+ .nif = ARRAY_SIZE(desc_iface_bluetooth),
+ .ifs = desc_iface_bluetooth,
+ },
+ },
};
-static const uint8_t qemu_bt_config_descriptor[] = {
- /* one configuration */
- 0x09, /* u8 bLength; */
- USB_DT_CONFIG, /* u8 bDescriptorType; */
- 0xb1, 0x00, /* u16 wTotalLength; */
- 0x02, /* u8 bNumInterfaces; (2) */
- 0x01, /* u8 bConfigurationValue; */
- 0x00, /* u8 iConfiguration; */
- 0xc0, /* u8 bmAttributes;
- Bit 7: must be set,
- 6: Self-powered,
- 5: Remote wakeup,
- 4..0: resvd */
- 0x00, /* u8 MaxPower; */
-
- /* USB 1.1:
- * USB 2.0, single TT organization (mandatory):
- * one interface, protocol 0
- *
- * USB 2.0, multiple TT organization (optional):
- * two interfaces, protocols 1 (like single TT)
- * and 2 (multiple TT mode) ... config is
- * sometimes settable
- * NOT IMPLEMENTED
- */
-
- /* interface one */
- 0x09, /* u8 if_bLength; */
- USB_DT_INTERFACE, /* u8 if_bDescriptorType; */
- 0x00, /* u8 if_bInterfaceNumber; */
- 0x00, /* u8 if_bAlternateSetting; */
- 0x03, /* u8 if_bNumEndpoints; */
- 0xe0, /* u8 if_bInterfaceClass; Wireless */
- 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */
- 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */
- 0x00, /* u8 if_iInterface; */
-
- /* endpoint one */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_IN | USB_EVT_EP, /* u8 ep_bEndpointAddress; */
- 0x03, /* u8 ep_bmAttributes; Interrupt */
- 0x10, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x02, /* u8 ep_bInterval; */
-
- /* endpoint two */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_OUT | USB_ACL_EP, /* u8 ep_bEndpointAddress; */
- 0x02, /* u8 ep_bmAttributes; Bulk */
- 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* endpoint three */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_IN | USB_ACL_EP, /* u8 ep_bEndpointAddress; */
- 0x02, /* u8 ep_bmAttributes; Bulk */
- 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* interface two setting one */
- 0x09, /* u8 if_bLength; */
- USB_DT_INTERFACE, /* u8 if_bDescriptorType; */
- 0x01, /* u8 if_bInterfaceNumber; */
- 0x00, /* u8 if_bAlternateSetting; */
- 0x02, /* u8 if_bNumEndpoints; */
- 0xe0, /* u8 if_bInterfaceClass; Wireless */
- 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */
- 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */
- 0x00, /* u8 if_iInterface; */
-
- /* endpoint one */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_OUT | USB_SCO_EP, /* u8 ep_bEndpointAddress; */
- 0x01, /* u8 ep_bmAttributes; Isochronous */
- 0x00, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* endpoint two */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_IN | USB_SCO_EP, /* u8 ep_bEndpointAddress; */
- 0x01, /* u8 ep_bmAttributes; Isochronous */
- 0x00, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* interface two setting two */
- 0x09, /* u8 if_bLength; */
- USB_DT_INTERFACE, /* u8 if_bDescriptorType; */
- 0x01, /* u8 if_bInterfaceNumber; */
- 0x01, /* u8 if_bAlternateSetting; */
- 0x02, /* u8 if_bNumEndpoints; */
- 0xe0, /* u8 if_bInterfaceClass; Wireless */
- 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */
- 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */
- 0x00, /* u8 if_iInterface; */
-
- /* endpoint one */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_OUT | USB_SCO_EP, /* u8 ep_bEndpointAddress; */
- 0x01, /* u8 ep_bmAttributes; Isochronous */
- 0x09, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* endpoint two */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_IN | USB_SCO_EP, /* u8 ep_bEndpointAddress; */
- 0x01, /* u8 ep_bmAttributes; Isochronous */
- 0x09, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* interface two setting three */
- 0x09, /* u8 if_bLength; */
- USB_DT_INTERFACE, /* u8 if_bDescriptorType; */
- 0x01, /* u8 if_bInterfaceNumber; */
- 0x02, /* u8 if_bAlternateSetting; */
- 0x02, /* u8 if_bNumEndpoints; */
- 0xe0, /* u8 if_bInterfaceClass; Wireless */
- 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */
- 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */
- 0x00, /* u8 if_iInterface; */
-
- /* endpoint one */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_OUT | USB_SCO_EP, /* u8 ep_bEndpointAddress; */
- 0x01, /* u8 ep_bmAttributes; Isochronous */
- 0x11, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* endpoint two */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_IN | USB_SCO_EP, /* u8 ep_bEndpointAddress; */
- 0x01, /* u8 ep_bmAttributes; Isochronous */
- 0x11, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* interface two setting four */
- 0x09, /* u8 if_bLength; */
- USB_DT_INTERFACE, /* u8 if_bDescriptorType; */
- 0x01, /* u8 if_bInterfaceNumber; */
- 0x03, /* u8 if_bAlternateSetting; */
- 0x02, /* u8 if_bNumEndpoints; */
- 0xe0, /* u8 if_bInterfaceClass; Wireless */
- 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */
- 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */
- 0x00, /* u8 if_iInterface; */
-
- /* endpoint one */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_OUT | USB_SCO_EP, /* u8 ep_bEndpointAddress; */
- 0x01, /* u8 ep_bmAttributes; Isochronous */
- 0x19, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* endpoint two */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_IN | USB_SCO_EP, /* u8 ep_bEndpointAddress; */
- 0x01, /* u8 ep_bmAttributes; Isochronous */
- 0x19, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* interface two setting five */
- 0x09, /* u8 if_bLength; */
- USB_DT_INTERFACE, /* u8 if_bDescriptorType; */
- 0x01, /* u8 if_bInterfaceNumber; */
- 0x04, /* u8 if_bAlternateSetting; */
- 0x02, /* u8 if_bNumEndpoints; */
- 0xe0, /* u8 if_bInterfaceClass; Wireless */
- 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */
- 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */
- 0x00, /* u8 if_iInterface; */
-
- /* endpoint one */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_OUT | USB_SCO_EP, /* u8 ep_bEndpointAddress; */
- 0x01, /* u8 ep_bmAttributes; Isochronous */
- 0x21, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* endpoint two */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_IN | USB_SCO_EP, /* u8 ep_bEndpointAddress; */
- 0x01, /* u8 ep_bmAttributes; Isochronous */
- 0x21, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* interface two setting six */
- 0x09, /* u8 if_bLength; */
- USB_DT_INTERFACE, /* u8 if_bDescriptorType; */
- 0x01, /* u8 if_bInterfaceNumber; */
- 0x05, /* u8 if_bAlternateSetting; */
- 0x02, /* u8 if_bNumEndpoints; */
- 0xe0, /* u8 if_bInterfaceClass; Wireless */
- 0x01, /* u8 if_bInterfaceSubClass; Radio Frequency */
- 0x01, /* u8 if_bInterfaceProtocol; Bluetooth */
- 0x00, /* u8 if_iInterface; */
-
- /* endpoint one */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_OUT | USB_SCO_EP, /* u8 ep_bEndpointAddress; */
- 0x01, /* u8 ep_bmAttributes; Isochronous */
- 0x31, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* endpoint two */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; */
- USB_DIR_IN | USB_SCO_EP, /* u8 ep_bEndpointAddress; */
- 0x01, /* u8 ep_bmAttributes; Isochronous */
- 0x31, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x01, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
-
- /* If implemented, the DFU interface descriptor goes here with no
- * endpoints or alternative settings. */
+static const USBDesc desc_bluetooth = {
+ .id = {
+ .idVendor = 0x0a12,
+ .idProduct = 0x0001,
+ .bcdDevice = 0x1958,
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = 0,
+ .iSerialNumber = STR_SERIALNUMBER,
+ },
+ .full = &desc_device_bluetooth,
+ .str = desc_strings,
};
static void usb_bt_fifo_reset(struct usb_hci_in_fifo_s *fifo)
@@ -424,8 +376,14 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
int index, int length, uint8_t *data)
{
struct USBBtState *s = (struct USBBtState *) dev->opaque;
- int ret = 0;
+ int ret;
+
+ ret = usb_desc_handle_control(dev, request, value, index, length, data);
+ if (ret >= 0) {
+ return ret;
+ }
+ ret = 0;
switch (request) {
case DeviceRequest | USB_REQ_GET_STATUS:
case InterfaceRequest | USB_REQ_GET_STATUS:
@@ -459,42 +417,14 @@ static int usb_bt_handle_control(USBDevice *dev, int request, int value,
dev->addr = value;
ret = 0;
break;
- case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
- switch (value >> 8) {
- case USB_DT_DEVICE:
- ret = sizeof(qemu_bt_dev_descriptor);
- memcpy(data, qemu_bt_dev_descriptor, ret);
- break;
- case USB_DT_CONFIG:
- ret = sizeof(qemu_bt_config_descriptor);
- memcpy(data, qemu_bt_config_descriptor, ret);
- break;
- case USB_DT_STRING:
- switch(value & 0xff) {
- case 0:
- /* language ids */
- data[0] = 4;
- data[1] = 3;
- data[2] = 0x09;
- data[3] = 0x04;
- ret = 4;
- break;
- default:
- goto fail;
- }
- break;
- default:
- goto fail;
- }
- break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
- data[0] = qemu_bt_config_descriptor[0x5];
+ data[0] = 1;
ret = 1;
s->config = 0;
break;
case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
ret = 0;
- if (value != qemu_bt_config_descriptor[0x5] && value != 0) {
+ if (value != 1 && value != 0) {
printf("%s: Wrong SET_CONFIGURATION request (%i)\n",
__FUNCTION__, value);
goto fail;
@@ -648,6 +578,7 @@ static struct USBDeviceInfo bt_info = {
.product_desc = "QEMU BT dongle",
.qdev.name = "usb-bt-dongle",
.qdev.size = sizeof(struct USBBtState),
+ .usb_desc = &desc_bluetooth,
.init = usb_bt_initfn,
.handle_packet = usb_generic_handle_packet,
.handle_reset = usb_bt_handle_reset,
commit 037a5203de7b12e2e33a7f71753002ae582ac196
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Thu Nov 25 16:12:06 2010 +0100
usb wacom: use new descriptor infrastructure.
Switch the usb wavom driver over to the
new descriptor infrastructure.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index 47f26cd..ffe6ac7 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -28,6 +28,7 @@
#include "hw.h"
#include "console.h"
#include "usb.h"
+#include "usb-desc.h"
/* Interface requests */
#define WACOM_GET_REPORT 0x2101
@@ -54,68 +55,75 @@ typedef struct USBWacomState {
int changed;
} USBWacomState;
-static const uint8_t qemu_wacom_dev_descriptor[] = {
- 0x12, /* u8 bLength; */
- 0x01, /* u8 bDescriptorType; Device */
- 0x10, 0x10, /* u16 bcdUSB; v1.10 */
+enum {
+ STR_MANUFACTURER = 1,
+ STR_PRODUCT,
+ STR_SERIALNUMBER,
+};
- 0x00, /* u8 bDeviceClass; */
- 0x00, /* u8 bDeviceSubClass; */
- 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
- 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
+static const USBDescStrings desc_strings = {
+ [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
+ [STR_PRODUCT] = "Wacom PenPartner",
+ [STR_SERIALNUMBER] = "1",
+};
- 0x6a, 0x05, /* u16 idVendor; */
- 0x00, 0x00, /* u16 idProduct; */
- 0x10, 0x42, /* u16 bcdDevice */
+static const USBDescIface desc_iface_wacom = {
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_HID,
+ .bInterfaceSubClass = 0x01, /* boot */
+ .bInterfaceProtocol = 0x02,
+ .ndesc = 1,
+ .descs = (USBDescOther[]) {
+ {
+ /* HID descriptor */
+ .data = (uint8_t[]) {
+ 0x09, /* u8 bLength */
+ 0x21, /* u8 bDescriptorType */
+ 0x01, 0x10, /* u16 HID_class */
+ 0x00, /* u8 country_code */
+ 0x01, /* u8 num_descriptors */
+ 0x22, /* u8 type: Report */
+ 0x6e, 0, /* u16 len */
+ },
+ },
+ },
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | 0x01,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 8,
+ .bInterval = 0x0a,
+ },
+ },
+};
- 0x01, /* u8 iManufacturer; */
- 0x02, /* u8 iProduct; */
- 0x00, /* u8 iSerialNumber; */
- 0x01, /* u8 bNumConfigurations; */
+static const USBDescDevice desc_device_wacom = {
+ .bcdUSB = 0x0110,
+ .bMaxPacketSize0 = 8,
+ .bNumConfigurations = 1,
+ .confs = (USBDescConfig[]) {
+ {
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .bmAttributes = 0x80,
+ .bMaxPower = 40,
+ .ifs = &desc_iface_wacom,
+ },
+ },
};
-static const uint8_t qemu_wacom_config_descriptor[] = {
- /* one configuration */
- 0x09, /* u8 bLength; */
- 0x02, /* u8 bDescriptorType; Configuration */
- 0x22, 0x00, /* u16 wTotalLength; */
- 0x01, /* u8 bNumInterfaces; (1) */
- 0x01, /* u8 bConfigurationValue; */
- 0x00, /* u8 iConfiguration; */
- 0x80, /* u8 bmAttributes;
- Bit 7: must be set,
- 6: Self-powered,
- 5: Remote wakeup,
- 4..0: resvd */
- 40, /* u8 MaxPower; */
-
- /* one interface */
- 0x09, /* u8 if_bLength; */
- 0x04, /* u8 if_bDescriptorType; Interface */
- 0x00, /* u8 if_bInterfaceNumber; */
- 0x00, /* u8 if_bAlternateSetting; */
- 0x01, /* u8 if_bNumEndpoints; */
- 0x03, /* u8 if_bInterfaceClass; HID */
- 0x01, /* u8 if_bInterfaceSubClass; Boot */
- 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
- 0x00, /* u8 if_iInterface; */
-
- /* HID descriptor */
- 0x09, /* u8 bLength; */
- 0x21, /* u8 bDescriptorType; */
- 0x01, 0x10, /* u16 HID_class */
- 0x00, /* u8 country_code */
- 0x01, /* u8 num_descriptors */
- 0x22, /* u8 type; Report */
- 0x6e, 0x00, /* u16 len */
-
- /* one endpoint (status change endpoint) */
- 0x07, /* u8 ep_bLength; */
- 0x05, /* u8 ep_bDescriptorType; Endpoint */
- 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
- 0x03, /* u8 ep_bmAttributes; Interrupt */
- 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x0a, /* u8 ep_bInterval; */
+static const USBDesc desc_wacom = {
+ .id = {
+ .idVendor = 0x056a,
+ .idProduct = 0x0000,
+ .bcdDevice = 0x4210,
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT,
+ .iSerialNumber = STR_SERIALNUMBER,
+ },
+ .full = &desc_device_wacom,
+ .str = desc_strings,
};
static void usb_mouse_event(void *opaque,
@@ -245,8 +253,14 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
int index, int length, uint8_t *data)
{
USBWacomState *s = (USBWacomState *) dev;
- int ret = 0;
+ int ret;
+
+ ret = usb_desc_handle_control(dev, request, value, index, length, data);
+ if (ret >= 0) {
+ return ret;
+ }
+ ret = 0;
switch (request) {
case DeviceRequest | USB_REQ_GET_STATUS:
data[0] = (1 << USB_DEVICE_SELF_POWERED) |
@@ -274,53 +288,6 @@ static int usb_wacom_handle_control(USBDevice *dev, int request, int value,
dev->addr = value;
ret = 0;
break;
- case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
- switch (value >> 8) {
- case USB_DT_DEVICE:
- memcpy(data, qemu_wacom_dev_descriptor,
- sizeof(qemu_wacom_dev_descriptor));
- ret = sizeof(qemu_wacom_dev_descriptor);
- break;
- case USB_DT_CONFIG:
- memcpy(data, qemu_wacom_config_descriptor,
- sizeof(qemu_wacom_config_descriptor));
- ret = sizeof(qemu_wacom_config_descriptor);
- break;
- case USB_DT_STRING:
- switch (value & 0xff) {
- case 0:
- /* language ids */
- data[0] = 4;
- data[1] = 3;
- data[2] = 0x09;
- data[3] = 0x04;
- ret = 4;
- break;
- case 1:
- /* serial number */
- ret = set_usb_string(data, "1");
- break;
- case 2:
- ret = set_usb_string(data, "Wacom PenPartner");
- break;
- case 3:
- /* vendor description */
- ret = set_usb_string(data, "QEMU " QEMU_VERSION);
- break;
- case 4:
- ret = set_usb_string(data, "Wacom Tablet");
- break;
- case 5:
- ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
- break;
- default:
- goto fail;
- }
- break;
- default:
- goto fail;
- }
- break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
@@ -420,6 +387,7 @@ static struct USBDeviceInfo wacom_info = {
.qdev.name = "usb-wacom-tablet",
.qdev.desc = "QEMU PenPartner Tablet",
.usbdevice_name = "wacom-tablet",
+ .usb_desc = &desc_wacom,
.qdev.size = sizeof(USBWacomState),
.init = usb_wacom_initfn,
.handle_packet = usb_generic_handle_packet,
commit 81bfd2f24678c5f36d9a6942af3d4b48e4b87226
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Nov 17 11:05:41 2010 +0100
usb storage: use new descriptor infrastructure.
Switch the usb storage driver over to the
new descriptor infrastructure.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 0a95d8d..20ab886 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -11,6 +11,7 @@
#include "qemu-option.h"
#include "qemu-config.h"
#include "usb.h"
+#include "usb-desc.h"
#include "scsi.h"
#include "console.h"
#include "monitor.h"
@@ -72,69 +73,62 @@ struct usb_msd_csw {
uint8_t status;
};
-static const uint8_t qemu_msd_dev_descriptor[] = {
- 0x12, /* u8 bLength; */
- 0x01, /* u8 bDescriptorType; Device */
- 0x00, 0x01, /* u16 bcdUSB; v1.0 */
-
- 0x00, /* u8 bDeviceClass; */
- 0x00, /* u8 bDeviceSubClass; */
- 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
- 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
-
- /* Vendor and product id are arbitrary. */
- 0x00, 0x00, /* u16 idVendor; */
- 0x00, 0x00, /* u16 idProduct; */
- 0x00, 0x00, /* u16 bcdDevice */
-
- 0x01, /* u8 iManufacturer; */
- 0x02, /* u8 iProduct; */
- 0x03, /* u8 iSerialNumber; */
- 0x01 /* u8 bNumConfigurations; */
+enum {
+ STR_MANUFACTURER = 1,
+ STR_PRODUCT,
+ STR_SERIALNUMBER,
};
-static const uint8_t qemu_msd_config_descriptor[] = {
-
- /* one configuration */
- 0x09, /* u8 bLength; */
- 0x02, /* u8 bDescriptorType; Configuration */
- 0x20, 0x00, /* u16 wTotalLength; */
- 0x01, /* u8 bNumInterfaces; (1) */
- 0x01, /* u8 bConfigurationValue; */
- 0x00, /* u8 iConfiguration; */
- 0xc0, /* u8 bmAttributes;
- Bit 7: must be set,
- 6: Self-powered,
- 5: Remote wakeup,
- 4..0: resvd */
- 0x00, /* u8 MaxPower; */
-
- /* one interface */
- 0x09, /* u8 if_bLength; */
- 0x04, /* u8 if_bDescriptorType; Interface */
- 0x00, /* u8 if_bInterfaceNumber; */
- 0x00, /* u8 if_bAlternateSetting; */
- 0x02, /* u8 if_bNumEndpoints; */
- 0x08, /* u8 if_bInterfaceClass; MASS STORAGE */
- 0x06, /* u8 if_bInterfaceSubClass; SCSI */
- 0x50, /* u8 if_bInterfaceProtocol; Bulk Only */
- 0x00, /* u8 if_iInterface; */
-
- /* Bulk-In endpoint */
- 0x07, /* u8 ep_bLength; */
- 0x05, /* u8 ep_bDescriptorType; Endpoint */
- 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
- 0x02, /* u8 ep_bmAttributes; Bulk */
- 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x00, /* u8 ep_bInterval; */
-
- /* Bulk-Out endpoint */
- 0x07, /* u8 ep_bLength; */
- 0x05, /* u8 ep_bDescriptorType; Endpoint */
- 0x02, /* u8 ep_bEndpointAddress; OUT Endpoint 2 */
- 0x02, /* u8 ep_bmAttributes; Bulk */
- 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x00 /* u8 ep_bInterval; */
+static const USBDescStrings desc_strings = {
+ [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
+ [STR_PRODUCT] = "QEMU USB HARDDRIVE",
+ [STR_SERIALNUMBER] = "1",
+};
+
+static const USBDescIface desc_iface0 = {
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_MASS_STORAGE,
+ .bInterfaceSubClass = 0x06, /* SCSI */
+ .bInterfaceProtocol = 0x50, /* Bulk */
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | 0x01,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ },{
+ .bEndpointAddress = USB_DIR_OUT | 0x02,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ },
+ }
+};
+
+static const USBDescDevice desc_device = {
+ .bcdUSB = 0x0100,
+ .bMaxPacketSize0 = 8,
+ .bNumConfigurations = 1,
+ .confs = (USBDescConfig[]) {
+ {
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .bmAttributes = 0xc0,
+ .ifs = &desc_iface0,
+ },
+ },
+};
+
+static const USBDesc desc = {
+ .id = {
+ .idVendor = 0,
+ .idProduct = 0,
+ .bcdDevice = 0,
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT,
+ .iSerialNumber = STR_SERIALNUMBER,
+ },
+ .full = &desc_device,
+ .str = desc_strings,
};
static void usb_msd_copy_data(MSDState *s)
@@ -236,8 +230,14 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
int index, int length, uint8_t *data)
{
MSDState *s = (MSDState *)dev;
- int ret = 0;
+ int ret;
+ ret = usb_desc_handle_control(dev, request, value, index, length, data);
+ if (ret >= 0) {
+ return ret;
+ }
+
+ ret = 0;
switch (request) {
case DeviceRequest | USB_REQ_GET_STATUS:
data[0] = (1 << USB_DEVICE_SELF_POWERED) |
@@ -265,48 +265,6 @@ static int usb_msd_handle_control(USBDevice *dev, int request, int value,
dev->addr = value;
ret = 0;
break;
- case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
- switch(value >> 8) {
- case USB_DT_DEVICE:
- memcpy(data, qemu_msd_dev_descriptor,
- sizeof(qemu_msd_dev_descriptor));
- ret = sizeof(qemu_msd_dev_descriptor);
- break;
- case USB_DT_CONFIG:
- memcpy(data, qemu_msd_config_descriptor,
- sizeof(qemu_msd_config_descriptor));
- ret = sizeof(qemu_msd_config_descriptor);
- break;
- case USB_DT_STRING:
- switch(value & 0xff) {
- case 0:
- /* language ids */
- data[0] = 4;
- data[1] = 3;
- data[2] = 0x09;
- data[3] = 0x04;
- ret = 4;
- break;
- case 1:
- /* vendor description */
- ret = set_usb_string(data, "QEMU " QEMU_VERSION);
- break;
- case 2:
- /* product description */
- ret = set_usb_string(data, "QEMU USB HARDDRIVE");
- break;
- case 3:
- /* serial number */
- ret = set_usb_string(data, "1");
- break;
- default:
- goto fail;
- }
- break;
- default:
- goto fail;
- }
- break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
@@ -625,6 +583,7 @@ static struct USBDeviceInfo msd_info = {
.product_desc = "QEMU USB MSD",
.qdev.name = "usb-storage",
.qdev.size = sizeof(MSDState),
+ .usb_desc = &desc,
.init = usb_msd_initfn,
.handle_packet = usb_generic_handle_packet,
.handle_reset = usb_msd_handle_reset,
commit f29783f72ea77dfbd7ea0c993d62d253d4c4e023
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Nov 17 11:05:32 2010 +0100
usb serial: use new descriptor infrastructure.
Switch the usb serial drivers (serial, braille) over to the
new descriptor infrastructure.
Note that this removes the freely configurable vendor and product id
properties. I think the only reason this was configurable is that the
only difference between the serial and the braille device is the
vendor+product id. Of course the serial and braille devices keep their
different IDs, but they can't be overritten from the command line any
more.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index c19580f..f89eb9b 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -11,6 +11,7 @@
#include "qemu-common.h"
#include "qemu-error.h"
#include "usb.h"
+#include "usb-desc.h"
#include "qemu-char.h"
//#define DEBUG_Serial
@@ -91,8 +92,6 @@ do { printf("usb-serial: " fmt , ## __VA_ARGS__); } while (0)
typedef struct {
USBDevice dev;
- uint32_t vendorid;
- uint32_t productid;
uint8_t recv_buf[RECV_BUF];
uint16_t recv_ptr;
uint16_t recv_used;
@@ -104,69 +103,78 @@ typedef struct {
CharDriverState *cs;
} USBSerialState;
-static const uint8_t qemu_serial_dev_descriptor[] = {
- 0x12, /* u8 bLength; */
- 0x01, /* u8 bDescriptorType; Device */
- 0x00, 0x02, /* u16 bcdUSB; v2.0 */
-
- 0x00, /* u8 bDeviceClass; */
- 0x00, /* u8 bDeviceSubClass; */
- 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
- 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
-
- /* Vendor and product id are arbitrary. */
- 0x03, 0x04, /* u16 idVendor; */
- 0x00, 0xFF, /* u16 idProduct; */
- 0x00, 0x04, /* u16 bcdDevice */
-
- 0x01, /* u8 iManufacturer; */
- 0x02, /* u8 iProduct; */
- 0x03, /* u8 iSerialNumber; */
- 0x01 /* u8 bNumConfigurations; */
+enum {
+ STR_MANUFACTURER = 1,
+ STR_PRODUCT_SERIAL,
+ STR_PRODUCT_BRAILLE,
+ STR_SERIALNUMBER,
};
-static const uint8_t qemu_serial_config_descriptor[] = {
-
- /* one configuration */
- 0x09, /* u8 bLength; */
- 0x02, /* u8 bDescriptorType; Configuration */
- 0x20, 0x00, /* u16 wTotalLength; */
- 0x01, /* u8 bNumInterfaces; (1) */
- 0x01, /* u8 bConfigurationValue; */
- 0x00, /* u8 iConfiguration; */
- 0x80, /* u8 bmAttributes;
- Bit 7: must be set,
- 6: Self-powered,
- 5: Remote wakeup,
- 4..0: resvd */
- 100/2, /* u8 MaxPower; */
-
- /* one interface */
- 0x09, /* u8 if_bLength; */
- 0x04, /* u8 if_bDescriptorType; Interface */
- 0x00, /* u8 if_bInterfaceNumber; */
- 0x00, /* u8 if_bAlternateSetting; */
- 0x02, /* u8 if_bNumEndpoints; */
- 0xff, /* u8 if_bInterfaceClass; Vendor Specific */
- 0xff, /* u8 if_bInterfaceSubClass; Vendor Specific */
- 0xff, /* u8 if_bInterfaceProtocol; Vendor Specific */
- 0x02, /* u8 if_iInterface; */
-
- /* Bulk-In endpoint */
- 0x07, /* u8 ep_bLength; */
- 0x05, /* u8 ep_bDescriptorType; Endpoint */
- 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
- 0x02, /* u8 ep_bmAttributes; Bulk */
- 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x00, /* u8 ep_bInterval; */
-
- /* Bulk-Out endpoint */
- 0x07, /* u8 ep_bLength; */
- 0x05, /* u8 ep_bDescriptorType; Endpoint */
- 0x02, /* u8 ep_bEndpointAddress; OUT Endpoint 2 */
- 0x02, /* u8 ep_bmAttributes; Bulk */
- 0x40, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x00 /* u8 ep_bInterval; */
+static const USBDescStrings desc_strings = {
+ [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
+ [STR_PRODUCT_SERIAL] = "QEMU USB SERIAL",
+ [STR_PRODUCT_BRAILLE] = "QEMU USB BRAILLE",
+ [STR_SERIALNUMBER] = "1",
+};
+
+static const USBDescIface desc_iface0 = {
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = 0xff,
+ .bInterfaceSubClass = 0xff,
+ .bInterfaceProtocol = 0xff,
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | 0x01,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ },{
+ .bEndpointAddress = USB_DIR_OUT | 0x02,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = 64,
+ },
+ }
+};
+
+static const USBDescDevice desc_device = {
+ .bcdUSB = 0x0200,
+ .bMaxPacketSize0 = 8,
+ .bNumConfigurations = 1,
+ .confs = (USBDescConfig[]) {
+ {
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .bmAttributes = 0x80,
+ .bMaxPower = 50,
+ .ifs = &desc_iface0,
+ },
+ },
+};
+
+static const USBDesc desc_serial = {
+ .id = {
+ .idVendor = 0x0403,
+ .idProduct = 0x6001,
+ .bcdDevice = 0x0400,
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT_SERIAL,
+ .iSerialNumber = STR_SERIALNUMBER,
+ },
+ .full = &desc_device,
+ .str = desc_strings,
+};
+
+static const USBDesc desc_braille = {
+ .id = {
+ .idVendor = 0x0403,
+ .idProduct = 0xfe72,
+ .bcdDevice = 0x0400,
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT_BRAILLE,
+ .iSerialNumber = STR_SERIALNUMBER,
+ },
+ .full = &desc_device,
+ .str = desc_strings,
};
static void usb_serial_reset(USBSerialState *s)
@@ -214,9 +222,15 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
int index, int length, uint8_t *data)
{
USBSerialState *s = (USBSerialState *)dev;
- int ret = 0;
+ int ret;
+
+ DPRINTF("got control %x, value %x\n",request, value);
+ ret = usb_desc_handle_control(dev, request, value, index, length, data);
+ if (ret >= 0) {
+ return ret;
+ }
- //DPRINTF("got control %x, value %x\n",request, value);
+ ret = 0;
switch (request) {
case DeviceRequest | USB_REQ_GET_STATUS:
data[0] = (0 << USB_DEVICE_SELF_POWERED) |
@@ -244,52 +258,6 @@ static int usb_serial_handle_control(USBDevice *dev, int request, int value,
dev->addr = value;
ret = 0;
break;
- case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
- switch(value >> 8) {
- case USB_DT_DEVICE:
- memcpy(data, qemu_serial_dev_descriptor,
- sizeof(qemu_serial_dev_descriptor));
- data[8] = s->vendorid & 0xff;
- data[9] = ((s->vendorid) >> 8) & 0xff;
- data[10] = s->productid & 0xff;
- data[11] = ((s->productid) >> 8) & 0xff;
- ret = sizeof(qemu_serial_dev_descriptor);
- break;
- case USB_DT_CONFIG:
- memcpy(data, qemu_serial_config_descriptor,
- sizeof(qemu_serial_config_descriptor));
- ret = sizeof(qemu_serial_config_descriptor);
- break;
- case USB_DT_STRING:
- switch(value & 0xff) {
- case 0:
- /* language ids */
- data[0] = 4;
- data[1] = 3;
- data[2] = 0x09;
- data[3] = 0x04;
- ret = 4;
- break;
- case 1:
- /* vendor description */
- ret = set_usb_string(data, "QEMU " QEMU_VERSION);
- break;
- case 2:
- /* product description */
- ret = set_usb_string(data, "QEMU USB SERIAL");
- break;
- case 3:
- /* serial number */
- ret = set_usb_string(data, "1");
- break;
- default:
- goto fail;
- }
- break;
- default:
- goto fail;
- }
- break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
@@ -633,6 +601,7 @@ static struct USBDeviceInfo serial_info = {
.product_desc = "QEMU USB Serial",
.qdev.name = "usb-serial",
.qdev.size = sizeof(USBSerialState),
+ .usb_desc = &desc_serial,
.init = usb_serial_initfn,
.handle_packet = usb_generic_handle_packet,
.handle_reset = usb_serial_handle_reset,
@@ -642,9 +611,7 @@ static struct USBDeviceInfo serial_info = {
.usbdevice_name = "serial",
.usbdevice_init = usb_serial_init,
.qdev.props = (Property[]) {
- DEFINE_PROP_CHR("chardev", USBSerialState, cs),
- DEFINE_PROP_HEX32("vendorid", USBSerialState, vendorid, 0x0403),
- DEFINE_PROP_HEX32("productid", USBSerialState, productid, 0x6001),
+ DEFINE_PROP_CHR("chardev", USBSerialState, cs),
DEFINE_PROP_END_OF_LIST(),
},
};
@@ -653,6 +620,7 @@ static struct USBDeviceInfo braille_info = {
.product_desc = "QEMU USB Braille",
.qdev.name = "usb-braille",
.qdev.size = sizeof(USBSerialState),
+ .usb_desc = &desc_braille,
.init = usb_serial_initfn,
.handle_packet = usb_generic_handle_packet,
.handle_reset = usb_serial_handle_reset,
@@ -662,9 +630,7 @@ static struct USBDeviceInfo braille_info = {
.usbdevice_name = "braille",
.usbdevice_init = usb_braille_init,
.qdev.props = (Property[]) {
- DEFINE_PROP_CHR("chardev", USBSerialState, cs),
- DEFINE_PROP_HEX32("vendorid", USBSerialState, vendorid, 0x0403),
- DEFINE_PROP_HEX32("productid", USBSerialState, productid, 0xfe72),
+ DEFINE_PROP_CHR("chardev", USBSerialState, cs),
DEFINE_PROP_END_OF_LIST(),
},
};
commit 0e4e9695d5c4a5923094906433b5f7b431ba35e4
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Nov 17 11:05:05 2010 +0100
usb hid: use new descriptor infrastructure.
Switch the usb hid drivers (keyboard, mouse, tablet) over to the
new descriptor infrastructure.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 882d933..74d17fc 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -25,6 +25,7 @@
#include "hw.h"
#include "console.h"
#include "usb.h"
+#include "usb-desc.h"
#include "sysemu.h"
/* HID interface requests */
@@ -73,190 +74,206 @@ typedef struct USBHIDState {
void (*datain)(void *);
} USBHIDState;
-/* mostly the same values as the Bochs USB Mouse device */
-static const uint8_t qemu_mouse_dev_descriptor[] = {
- 0x12, /* u8 bLength; */
- 0x01, /* u8 bDescriptorType; Device */
- 0x00, 0x01, /* u16 bcdUSB; v1.0 */
-
- 0x00, /* u8 bDeviceClass; */
- 0x00, /* u8 bDeviceSubClass; */
- 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */
- 0x08, /* u8 bMaxPacketSize0; 8 Bytes */
-
- 0x27, 0x06, /* u16 idVendor; */
- 0x01, 0x00, /* u16 idProduct; */
- 0x00, 0x00, /* u16 bcdDevice */
-
- 0x03, /* u8 iManufacturer; */
- 0x02, /* u8 iProduct; */
- 0x01, /* u8 iSerialNumber; */
- 0x01 /* u8 bNumConfigurations; */
+enum {
+ STR_MANUFACTURER = 1,
+ STR_PRODUCT_MOUSE,
+ STR_PRODUCT_TABLET,
+ STR_PRODUCT_KEYBOARD,
+ STR_SERIALNUMBER,
+ STR_CONFIG_MOUSE,
+ STR_CONFIG_TABLET,
+ STR_CONFIG_KEYBOARD,
};
-static const uint8_t qemu_mouse_config_descriptor[] = {
- /* one configuration */
- 0x09, /* u8 bLength; */
- 0x02, /* u8 bDescriptorType; Configuration */
- 0x22, 0x00, /* u16 wTotalLength; */
- 0x01, /* u8 bNumInterfaces; (1) */
- 0x01, /* u8 bConfigurationValue; */
- 0x04, /* u8 iConfiguration; */
- 0xe0, /* u8 bmAttributes;
- Bit 7: must be set,
- 6: Self-powered,
- 5: Remote wakeup,
- 4..0: resvd */
- 50, /* u8 MaxPower; */
-
- /* USB 1.1:
- * USB 2.0, single TT organization (mandatory):
- * one interface, protocol 0
- *
- * USB 2.0, multiple TT organization (optional):
- * two interfaces, protocols 1 (like single TT)
- * and 2 (multiple TT mode) ... config is
- * sometimes settable
- * NOT IMPLEMENTED
- */
-
- /* one interface */
- 0x09, /* u8 if_bLength; */
- 0x04, /* u8 if_bDescriptorType; Interface */
- 0x00, /* u8 if_bInterfaceNumber; */
- 0x00, /* u8 if_bAlternateSetting; */
- 0x01, /* u8 if_bNumEndpoints; */
- 0x03, /* u8 if_bInterfaceClass; */
- 0x01, /* u8 if_bInterfaceSubClass; */
- 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
- 0x07, /* u8 if_iInterface; */
-
- /* HID descriptor */
- 0x09, /* u8 bLength; */
- 0x21, /* u8 bDescriptorType; */
- 0x01, 0x00, /* u16 HID_class */
- 0x00, /* u8 country_code */
- 0x01, /* u8 num_descriptors */
- 0x22, /* u8 type; Report */
- 52, 0, /* u16 len */
-
- /* one endpoint (status change endpoint) */
- 0x07, /* u8 ep_bLength; */
- 0x05, /* u8 ep_bDescriptorType; Endpoint */
- 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
- 0x03, /* u8 ep_bmAttributes; Interrupt */
- 0x04, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
+static const USBDescStrings desc_strings = {
+ [STR_MANUFACTURER] = "QEMU " QEMU_VERSION,
+ [STR_PRODUCT_MOUSE] = "QEMU USB Mouse",
+ [STR_PRODUCT_TABLET] = "QEMU USB Tablet",
+ [STR_PRODUCT_KEYBOARD] = "QEMU USB Keyboard",
+ [STR_SERIALNUMBER] = "1",
+ [STR_CONFIG_MOUSE] = "HID Mouse",
+ [STR_CONFIG_TABLET] = "HID Tablet",
+ [STR_CONFIG_KEYBOARD] = "HID Keyboard",
};
-static const uint8_t qemu_tablet_config_descriptor[] = {
- /* one configuration */
- 0x09, /* u8 bLength; */
- 0x02, /* u8 bDescriptorType; Configuration */
- 0x22, 0x00, /* u16 wTotalLength; */
- 0x01, /* u8 bNumInterfaces; (1) */
- 0x01, /* u8 bConfigurationValue; */
- 0x05, /* u8 iConfiguration; */
- 0xa0, /* u8 bmAttributes;
- Bit 7: must be set,
- 6: Self-powered,
- 5: Remote wakeup,
- 4..0: resvd */
- 50, /* u8 MaxPower; */
-
- /* USB 1.1:
- * USB 2.0, single TT organization (mandatory):
- * one interface, protocol 0
- *
- * USB 2.0, multiple TT organization (optional):
- * two interfaces, protocols 1 (like single TT)
- * and 2 (multiple TT mode) ... config is
- * sometimes settable
- * NOT IMPLEMENTED
- */
-
- /* one interface */
- 0x09, /* u8 if_bLength; */
- 0x04, /* u8 if_bDescriptorType; Interface */
- 0x00, /* u8 if_bInterfaceNumber; */
- 0x00, /* u8 if_bAlternateSetting; */
- 0x01, /* u8 if_bNumEndpoints; */
- 0x03, /* u8 if_bInterfaceClass; */
- 0x01, /* u8 if_bInterfaceSubClass; */
- 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */
- 0x07, /* u8 if_iInterface; */
-
- /* HID descriptor */
- 0x09, /* u8 bLength; */
- 0x21, /* u8 bDescriptorType; */
- 0x01, 0x00, /* u16 HID_class */
- 0x00, /* u8 country_code */
- 0x01, /* u8 num_descriptors */
- 0x22, /* u8 type; Report */
- 74, 0, /* u16 len */
-
- /* one endpoint (status change endpoint) */
- 0x07, /* u8 ep_bLength; */
- 0x05, /* u8 ep_bDescriptorType; Endpoint */
- 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
- 0x03, /* u8 ep_bmAttributes; Interrupt */
- 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
+static const USBDescIface desc_iface_mouse = {
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_HID,
+ .bInterfaceSubClass = 0x01, /* boot */
+ .bInterfaceProtocol = 0x02,
+ .ndesc = 1,
+ .descs = (USBDescOther[]) {
+ {
+ /* HID descriptor */
+ .data = (uint8_t[]) {
+ 0x09, /* u8 bLength */
+ USB_DT_HID, /* u8 bDescriptorType */
+ 0x01, 0x00, /* u16 HID_class */
+ 0x00, /* u8 country_code */
+ 0x01, /* u8 num_descriptors */
+ USB_DT_REPORT, /* u8 type: Report */
+ 52, 0, /* u16 len */
+ },
+ },
+ },
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | 0x01,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 4,
+ .bInterval = 0x0a,
+ },
+ },
};
-static const uint8_t qemu_keyboard_config_descriptor[] = {
- /* one configuration */
- 0x09, /* u8 bLength; */
- USB_DT_CONFIG, /* u8 bDescriptorType; Configuration */
- 0x22, 0x00, /* u16 wTotalLength; */
- 0x01, /* u8 bNumInterfaces; (1) */
- 0x01, /* u8 bConfigurationValue; */
- 0x06, /* u8 iConfiguration; */
- 0xa0, /* u8 bmAttributes;
- Bit 7: must be set,
- 6: Self-powered,
- 5: Remote wakeup,
- 4..0: resvd */
- 0x32, /* u8 MaxPower; */
-
- /* USB 1.1:
- * USB 2.0, single TT organization (mandatory):
- * one interface, protocol 0
- *
- * USB 2.0, multiple TT organization (optional):
- * two interfaces, protocols 1 (like single TT)
- * and 2 (multiple TT mode) ... config is
- * sometimes settable
- * NOT IMPLEMENTED
- */
-
- /* one interface */
- 0x09, /* u8 if_bLength; */
- USB_DT_INTERFACE, /* u8 if_bDescriptorType; Interface */
- 0x00, /* u8 if_bInterfaceNumber; */
- 0x00, /* u8 if_bAlternateSetting; */
- 0x01, /* u8 if_bNumEndpoints; */
- 0x03, /* u8 if_bInterfaceClass; HID */
- 0x01, /* u8 if_bInterfaceSubClass; Boot */
- 0x01, /* u8 if_bInterfaceProtocol; Keyboard */
- 0x07, /* u8 if_iInterface; */
-
- /* HID descriptor */
- 0x09, /* u8 bLength; */
- USB_DT_HID, /* u8 bDescriptorType; */
- 0x11, 0x01, /* u16 HID_class */
- 0x00, /* u8 country_code */
- 0x01, /* u8 num_descriptors */
- USB_DT_REPORT, /* u8 type; Report */
- 0x3f, 0x00, /* u16 len */
-
- /* one endpoint (status change endpoint) */
- 0x07, /* u8 ep_bLength; */
- USB_DT_ENDPOINT, /* u8 ep_bDescriptorType; Endpoint */
- USB_DIR_IN | 0x01, /* u8 ep_bEndpointAddress; IN Endpoint 1 */
- 0x03, /* u8 ep_bmAttributes; Interrupt */
- 0x08, 0x00, /* u16 ep_wMaxPacketSize; */
- 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */
+static const USBDescIface desc_iface_tablet = {
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_HID,
+ .bInterfaceSubClass = 0x01, /* boot */
+ .bInterfaceProtocol = 0x02,
+ .ndesc = 1,
+ .descs = (USBDescOther[]) {
+ {
+ /* HID descriptor */
+ .data = (uint8_t[]) {
+ 0x09, /* u8 bLength */
+ USB_DT_HID, /* u8 bDescriptorType */
+ 0x01, 0x00, /* u16 HID_class */
+ 0x00, /* u8 country_code */
+ 0x01, /* u8 num_descriptors */
+ USB_DT_REPORT, /* u8 type: Report */
+ 74, 0, /* u16 len */
+ },
+ },
+ },
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | 0x01,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 8,
+ .bInterval = 0x0a,
+ },
+ },
+};
+
+static const USBDescIface desc_iface_keyboard = {
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_HID,
+ .bInterfaceSubClass = 0x01, /* boot */
+ .bInterfaceProtocol = 0x01, /* keyboard */
+ .ndesc = 1,
+ .descs = (USBDescOther[]) {
+ {
+ /* HID descriptor */
+ .data = (uint8_t[]) {
+ 0x09, /* u8 bLength */
+ USB_DT_HID, /* u8 bDescriptorType */
+ 0x11, 0x01, /* u16 HID_class */
+ 0x00, /* u8 country_code */
+ 0x01, /* u8 num_descriptors */
+ USB_DT_REPORT, /* u8 type: Report */
+ 0x3f, 0, /* u16 len */
+ },
+ },
+ },
+ .eps = (USBDescEndpoint[]) {
+ {
+ .bEndpointAddress = USB_DIR_IN | 0x01,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 8,
+ .bInterval = 0x0a,
+ },
+ },
+};
+
+static const USBDescDevice desc_device_mouse = {
+ .bcdUSB = 0x0100,
+ .bMaxPacketSize0 = 8,
+ .bNumConfigurations = 1,
+ .confs = (USBDescConfig[]) {
+ {
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .iConfiguration = STR_CONFIG_MOUSE,
+ .bmAttributes = 0xa0,
+ .bMaxPower = 50,
+ .ifs = &desc_iface_mouse,
+ },
+ },
+};
+
+static const USBDescDevice desc_device_tablet = {
+ .bcdUSB = 0x0100,
+ .bMaxPacketSize0 = 8,
+ .bNumConfigurations = 1,
+ .confs = (USBDescConfig[]) {
+ {
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .iConfiguration = STR_CONFIG_TABLET,
+ .bmAttributes = 0xa0,
+ .bMaxPower = 50,
+ .ifs = &desc_iface_tablet,
+ },
+ },
+};
+
+static const USBDescDevice desc_device_keyboard = {
+ .bcdUSB = 0x0100,
+ .bMaxPacketSize0 = 8,
+ .bNumConfigurations = 1,
+ .confs = (USBDescConfig[]) {
+ {
+ .bNumInterfaces = 1,
+ .bConfigurationValue = 1,
+ .iConfiguration = STR_CONFIG_KEYBOARD,
+ .bmAttributes = 0xa0,
+ .bMaxPower = 50,
+ .ifs = &desc_iface_keyboard,
+ },
+ },
+};
+
+static const USBDesc desc_mouse = {
+ .id = {
+ .idVendor = 0x0627,
+ .idProduct = 0x0001,
+ .bcdDevice = 0,
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT_MOUSE,
+ .iSerialNumber = STR_SERIALNUMBER,
+ },
+ .full = &desc_device_mouse,
+ .str = desc_strings,
+};
+
+static const USBDesc desc_tablet = {
+ .id = {
+ .idVendor = 0x0627,
+ .idProduct = 0x0001,
+ .bcdDevice = 0,
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT_TABLET,
+ .iSerialNumber = STR_SERIALNUMBER,
+ },
+ .full = &desc_device_tablet,
+ .str = desc_strings,
+};
+
+static const USBDesc desc_keyboard = {
+ .id = {
+ .idVendor = 0x0627,
+ .idProduct = 0x0001,
+ .bcdDevice = 0,
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT_KEYBOARD,
+ .iSerialNumber = STR_SERIALNUMBER,
+ },
+ .full = &desc_device_keyboard,
+ .str = desc_strings,
};
static const uint8_t qemu_mouse_hid_report_descriptor[] = {
@@ -647,8 +664,14 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
int index, int length, uint8_t *data)
{
USBHIDState *s = (USBHIDState *)dev;
- int ret = 0;
+ int ret;
+ ret = usb_desc_handle_control(dev, request, value, index, length, data);
+ if (ret >= 0) {
+ return ret;
+ }
+
+ ret = 0;
switch(request) {
case DeviceRequest | USB_REQ_GET_STATUS:
data[0] = (1 << USB_DEVICE_SELF_POWERED) |
@@ -676,70 +699,6 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
dev->addr = value;
ret = 0;
break;
- case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
- switch(value >> 8) {
- case USB_DT_DEVICE:
- memcpy(data, qemu_mouse_dev_descriptor,
- sizeof(qemu_mouse_dev_descriptor));
- ret = sizeof(qemu_mouse_dev_descriptor);
- break;
- case USB_DT_CONFIG:
- if (s->kind == USB_MOUSE) {
- memcpy(data, qemu_mouse_config_descriptor,
- sizeof(qemu_mouse_config_descriptor));
- ret = sizeof(qemu_mouse_config_descriptor);
- } else if (s->kind == USB_TABLET) {
- memcpy(data, qemu_tablet_config_descriptor,
- sizeof(qemu_tablet_config_descriptor));
- ret = sizeof(qemu_tablet_config_descriptor);
- } else if (s->kind == USB_KEYBOARD) {
- memcpy(data, qemu_keyboard_config_descriptor,
- sizeof(qemu_keyboard_config_descriptor));
- ret = sizeof(qemu_keyboard_config_descriptor);
- }
- break;
- case USB_DT_STRING:
- switch(value & 0xff) {
- case 0:
- /* language ids */
- data[0] = 4;
- data[1] = 3;
- data[2] = 0x09;
- data[3] = 0x04;
- ret = 4;
- break;
- case 1:
- /* serial number */
- ret = set_usb_string(data, "1");
- break;
- case 2:
- /* product description */
- ret = set_usb_string(data, s->dev.product_desc);
- break;
- case 3:
- /* vendor description */
- ret = set_usb_string(data, "QEMU " QEMU_VERSION);
- break;
- case 4:
- ret = set_usb_string(data, "HID Mouse");
- break;
- case 5:
- ret = set_usb_string(data, "HID Tablet");
- break;
- case 6:
- ret = set_usb_string(data, "HID Keyboard");
- break;
- case 7:
- ret = set_usb_string(data, "Endpoint1 Interrupt Pipe");
- break;
- default:
- goto fail;
- }
- break;
- default:
- goto fail;
- }
- break;
case DeviceRequest | USB_REQ_GET_CONFIGURATION:
data[0] = 1;
ret = 1;
@@ -912,6 +871,7 @@ static struct USBDeviceInfo hid_info[] = {
.qdev.name = "usb-tablet",
.usbdevice_name = "tablet",
.qdev.size = sizeof(USBHIDState),
+ .usb_desc = &desc_tablet,
.init = usb_tablet_initfn,
.handle_packet = usb_generic_handle_packet,
.handle_reset = usb_mouse_handle_reset,
@@ -923,6 +883,7 @@ static struct USBDeviceInfo hid_info[] = {
.qdev.name = "usb-mouse",
.usbdevice_name = "mouse",
.qdev.size = sizeof(USBHIDState),
+ .usb_desc = &desc_mouse,
.init = usb_mouse_initfn,
.handle_packet = usb_generic_handle_packet,
.handle_reset = usb_mouse_handle_reset,
@@ -934,6 +895,7 @@ static struct USBDeviceInfo hid_info[] = {
.qdev.name = "usb-kbd",
.usbdevice_name = "keyboard",
.qdev.size = sizeof(USBHIDState),
+ .usb_desc = &desc_keyboard,
.init = usb_keyboard_initfn,
.handle_packet = usb_generic_handle_packet,
.handle_reset = usb_keyboard_handle_reset,
commit 37fb59d3032687b6f0d94c307bd0a846e0ca1fe0
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Nov 17 11:03:53 2010 +0100
usb: data structs and helpers for usb descriptors.
This patch adds hw/usb-desc.[ch] files. They carry data structures
for various usb descriptors and helper functions to generate usb
packets from the structures.
The intention is to have a internal representation of the device
desription which is more usable than the current char array blobs,
so we can have common code handle common usb device emulation using
the device description.
The usage of this infrastructure is optional for usb drivers as there
are cases such as pass-through where it probably isn't very useful.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/Makefile.objs b/Makefile.objs
index c3e52c5..fda366d 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -88,7 +88,7 @@ common-obj-y += eeprom93xx.o
common-obj-y += scsi-disk.o cdrom.o
common-obj-y += scsi-generic.o scsi-bus.o
common-obj-y += usb.o usb-hub.o usb-$(HOST_USB).o usb-hid.o usb-msd.o usb-wacom.o
-common-obj-y += usb-serial.o usb-net.o usb-bus.o
+common-obj-y += usb-serial.o usb-net.o usb-bus.o usb-desc.o
common-obj-$(CONFIG_SSI) += ssi.o
common-obj-$(CONFIG_SSI_SD) += ssi-sd.o
common-obj-$(CONFIG_SD) += sd.o
diff --git a/hw/usb-desc.c b/hw/usb-desc.c
new file mode 100644
index 0000000..559ced7
--- /dev/null
+++ b/hw/usb-desc.c
@@ -0,0 +1,238 @@
+#include "usb.h"
+#include "usb-desc.h"
+#include "trace.h"
+
+/* ------------------------------------------------------------------ */
+
+static uint8_t usb_lo(uint16_t val)
+{
+ return val & 0xff;
+}
+
+static uint8_t usb_hi(uint16_t val)
+{
+ return (val >> 8) & 0xff;
+}
+
+int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
+ uint8_t *dest, size_t len)
+{
+ uint8_t bLength = 0x12;
+
+ if (len < bLength) {
+ return -1;
+ }
+
+ dest[0x00] = bLength;
+ dest[0x01] = USB_DT_DEVICE;
+
+ dest[0x02] = usb_lo(dev->bcdUSB);
+ dest[0x03] = usb_hi(dev->bcdUSB);
+ dest[0x04] = dev->bDeviceClass;
+ dest[0x05] = dev->bDeviceSubClass;
+ dest[0x06] = dev->bDeviceProtocol;
+ dest[0x07] = dev->bMaxPacketSize0;
+
+ dest[0x08] = usb_lo(id->idVendor);
+ dest[0x09] = usb_hi(id->idVendor);
+ dest[0x0a] = usb_lo(id->idProduct);
+ dest[0x0b] = usb_hi(id->idProduct);
+ dest[0x0c] = usb_lo(id->bcdDevice);
+ dest[0x0d] = usb_hi(id->bcdDevice);
+ dest[0x0e] = id->iManufacturer;
+ dest[0x0f] = id->iProduct;
+ dest[0x10] = id->iSerialNumber;
+
+ dest[0x11] = dev->bNumConfigurations;
+
+ return bLength;
+}
+
+int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
+{
+ uint8_t bLength = 0x09;
+ uint16_t wTotalLength = 0;
+ int i, rc, count;
+
+ if (len < bLength) {
+ return -1;
+ }
+
+ dest[0x00] = bLength;
+ dest[0x01] = USB_DT_CONFIG;
+ dest[0x04] = conf->bNumInterfaces;
+ dest[0x05] = conf->bConfigurationValue;
+ dest[0x06] = conf->iConfiguration;
+ dest[0x07] = conf->bmAttributes;
+ dest[0x08] = conf->bMaxPower;
+ wTotalLength += bLength;
+
+ count = conf->nif ? conf->nif : conf->bNumInterfaces;
+ for (i = 0; i < count; i++) {
+ rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len - wTotalLength);
+ if (rc < 0) {
+ return rc;
+ }
+ wTotalLength += rc;
+ }
+
+ dest[0x02] = usb_lo(wTotalLength);
+ dest[0x03] = usb_hi(wTotalLength);
+ return wTotalLength;
+}
+
+int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
+{
+ uint8_t bLength = 0x09;
+ int i, rc, pos = 0;
+
+ if (len < bLength) {
+ return -1;
+ }
+
+ dest[0x00] = bLength;
+ dest[0x01] = USB_DT_INTERFACE;
+ dest[0x02] = iface->bInterfaceNumber;
+ dest[0x03] = iface->bAlternateSetting;
+ dest[0x04] = iface->bNumEndpoints;
+ dest[0x05] = iface->bInterfaceClass;
+ dest[0x06] = iface->bInterfaceSubClass;
+ dest[0x07] = iface->bInterfaceProtocol;
+ dest[0x08] = iface->iInterface;
+ pos += bLength;
+
+ for (i = 0; i < iface->ndesc; i++) {
+ rc = usb_desc_other(iface->descs + i, dest + pos, len - pos);
+ if (rc < 0) {
+ return rc;
+ }
+ pos += rc;
+ }
+
+ for (i = 0; i < iface->bNumEndpoints; i++) {
+ rc = usb_desc_endpoint(iface->eps + i, dest + pos, len - pos);
+ if (rc < 0) {
+ return rc;
+ }
+ pos += rc;
+ }
+
+ return pos;
+}
+
+int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
+{
+ uint8_t bLength = 0x07;
+
+ if (len < bLength) {
+ return -1;
+ }
+
+ dest[0x00] = bLength;
+ dest[0x01] = USB_DT_ENDPOINT;
+ dest[0x02] = ep->bEndpointAddress;
+ dest[0x03] = ep->bmAttributes;
+ dest[0x04] = usb_lo(ep->wMaxPacketSize);
+ dest[0x05] = usb_hi(ep->wMaxPacketSize);
+ dest[0x06] = ep->bInterval;
+
+ return bLength;
+}
+
+int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
+{
+ int bLength = desc->length ? desc->length : desc->data[0];
+
+ if (len < bLength) {
+ return -1;
+ }
+
+ memcpy(dest, desc->data, bLength);
+ return bLength;
+}
+
+int usb_desc_string(const char* const *str, int index, uint8_t *dest, size_t len)
+{
+ uint8_t bLength, pos, i;
+
+ if (len < 4) {
+ return -1;
+ }
+
+ if (index == 0) {
+ /* language ids */
+ dest[0] = 4;
+ dest[1] = USB_DT_STRING;
+ dest[2] = 0x09;
+ dest[3] = 0x04;
+ return 4;
+ }
+
+ if (str[index] == NULL) {
+ return 0;
+ }
+ bLength = strlen(str[index]) * 2 + 2;
+ dest[0] = bLength;
+ dest[1] = USB_DT_STRING;
+ i = 0; pos = 2;
+ while (pos+1 < bLength && pos+1 < len) {
+ dest[pos++] = str[index][i++];
+ dest[pos++] = 0;
+ }
+ return pos;
+}
+
+/* ------------------------------------------------------------------ */
+
+int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
+{
+ const USBDesc *desc = dev->info->usb_desc;
+ uint8_t buf[256];
+ uint8_t type = value >> 8;
+ uint8_t index = value & 0xff;
+ int ret = -1;
+
+ switch(type) {
+ case USB_DT_DEVICE:
+ ret = usb_desc_device(&desc->id, desc->full, buf, sizeof(buf));
+ trace_usb_desc_device(dev->addr, len, ret);
+ break;
+ case USB_DT_CONFIG:
+ if (index < desc->full->bNumConfigurations) {
+ ret = usb_desc_config(desc->full->confs + index, buf, sizeof(buf));
+ }
+ trace_usb_desc_config(dev->addr, index, len, ret);
+ break;
+ case USB_DT_STRING:
+ ret = usb_desc_string(desc->str, index, buf, sizeof(buf));
+ trace_usb_desc_string(dev->addr, index, len, ret);
+ break;
+ default:
+ fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
+ dev->addr, type, len);
+ break;
+ }
+
+ if (ret > 0) {
+ if (ret > len) {
+ ret = len;
+ }
+ memcpy(dest, buf, ret);
+ }
+ return ret;
+}
+
+int usb_desc_handle_control(USBDevice *dev, int request, int value,
+ int index, int length, uint8_t *data)
+{
+ const USBDesc *desc = dev->info->usb_desc;
+ int ret = -1;
+
+ assert(desc != NULL);
+ switch(request) {
+ case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+ ret = usb_desc_get_descriptor(dev, value, data, length);
+ break;
+ }
+ return ret;
+}
diff --git a/hw/usb-desc.h b/hw/usb-desc.h
new file mode 100644
index 0000000..d80efdb
--- /dev/null
+++ b/hw/usb-desc.h
@@ -0,0 +1,86 @@
+#ifndef QEMU_HW_USB_DESC_H
+#define QEMU_HW_USB_DESC_H
+
+#include <inttypes.h>
+
+struct USBDescID {
+ uint16_t idVendor;
+ uint16_t idProduct;
+ uint16_t bcdDevice;
+ uint8_t iManufacturer;
+ uint8_t iProduct;
+ uint8_t iSerialNumber;
+};
+
+struct USBDescDevice {
+ uint16_t bcdUSB;
+ uint8_t bDeviceClass;
+ uint8_t bDeviceSubClass;
+ uint8_t bDeviceProtocol;
+ uint8_t bMaxPacketSize0;
+ uint8_t bNumConfigurations;
+
+ const USBDescConfig *confs;
+};
+
+struct USBDescConfig {
+ uint8_t bNumInterfaces;
+ uint8_t bConfigurationValue;
+ uint8_t iConfiguration;
+ uint8_t bmAttributes;
+ uint8_t bMaxPower;
+
+ uint8_t nif;
+ const USBDescIface *ifs;
+};
+
+struct USBDescIface {
+ uint8_t bInterfaceNumber;
+ uint8_t bAlternateSetting;
+ uint8_t bNumEndpoints;
+ uint8_t bInterfaceClass;
+ uint8_t bInterfaceSubClass;
+ uint8_t bInterfaceProtocol;
+ uint8_t iInterface;
+
+ uint8_t ndesc;
+ USBDescOther *descs;
+ USBDescEndpoint *eps;
+};
+
+struct USBDescEndpoint {
+ uint8_t bEndpointAddress;
+ uint8_t bmAttributes;
+ uint16_t wMaxPacketSize;
+ uint8_t bInterval;
+};
+
+struct USBDescOther {
+ uint8_t length;
+ uint8_t *data;
+};
+
+typedef const char *USBDescStrings[256];
+
+struct USBDesc {
+ USBDescID id;
+ const USBDescDevice *full;
+ const USBDescDevice *high;
+ const char* const *str;
+};
+
+/* generate usb packages from structs */
+int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
+ uint8_t *dest, size_t len);
+int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len);
+int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len);
+int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
+int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
+int usb_desc_string(const char* const *str, int index, uint8_t *dest, size_t len);
+
+/* control message emulation helpers */
+int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len);
+int usb_desc_handle_control(USBDevice *dev, int request, int value,
+ int index, int length, uint8_t *data);
+
+#endif /* QEMU_HW_USB_DESC_H */
diff --git a/hw/usb.h b/hw/usb.h
index 0b32d77..a29b6d6 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -128,6 +128,14 @@ typedef struct USBDevice USBDevice;
typedef struct USBDeviceInfo USBDeviceInfo;
typedef struct USBPacket USBPacket;
+typedef struct USBDesc USBDesc;
+typedef struct USBDescID USBDescID;
+typedef struct USBDescDevice USBDescDevice;
+typedef struct USBDescConfig USBDescConfig;
+typedef struct USBDescIface USBDescIface;
+typedef struct USBDescEndpoint USBDescEndpoint;
+typedef struct USBDescOther USBDescOther;
+
/* definition of a USB device */
struct USBDevice {
DeviceState qdev;
@@ -190,6 +198,7 @@ struct USBDeviceInfo {
int (*handle_data)(USBDevice *dev, USBPacket *p);
const char *product_desc;
+ const USBDesc *usb_desc;
/* handle legacy -usbdevice command line options */
const char *usbdevice_name;
diff --git a/trace-events b/trace-events
index e8fed0f..8264ff0 100644
--- a/trace-events
+++ b/trace-events
@@ -190,6 +190,11 @@ disable sun4m_iommu_page_get_flags(uint64_t pa, uint64_t iopte, uint32_t ret) "g
disable sun4m_iommu_translate_pa(uint64_t addr, uint64_t pa, uint32_t iopte) "xlate dva %"PRIx64" => pa %"PRIx64" iopte = %x"
disable sun4m_iommu_bad_addr(uint64_t addr) "bad addr %"PRIx64""
+# hw/usb-desc.c
+disable usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
+disable usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
+disable usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
+
# vl.c
disable vm_state_notify(int running, int reason) "running %d reason %d"
commit 5d0d62feee8aa75525207ef24919c0522651a432
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Dec 17 11:11:25 2010 +0100
usb: update MAINTAINERS
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/MAINTAINERS b/MAINTAINERS
index 59effc7..4b07192 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -329,8 +329,8 @@ F: hw/lsi53c895a.c
F: hw/scsi*
USB
-M: qemu-devel at nongnu.org
-S: Odd Fixes
+M: Gerd Hoffmann <kraxel at redhat.com>
+S: Maintained
F: hw/usb*
vhost
commit 65d6dcbde84314c6d05a365a26a384f880a5c8fe
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date: Fri Dec 17 12:01:52 2010 +0000
docs: Document virtio PCI -device ioeventfd=on|off
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/docs/qdev-device-use.txt b/docs/qdev-device-use.txt
index f252c8e..f2f9b75 100644
--- a/docs/qdev-device-use.txt
+++ b/docs/qdev-device-use.txt
@@ -97,10 +97,13 @@ The -device argument differs in detail for each kind of drive:
* if=virtio
- -device virtio-blk-pci,drive=DRIVE-ID,class=C,vectors=V
+ -device virtio-blk-pci,drive=DRIVE-ID,class=C,vectors=V,ioeventfd=IOEVENTFD
This lets you control PCI device class and MSI-X vectors.
+ IOEVENTFD controls whether or not ioeventfd is used for virtqueue notify. It
+ can be set to on (default) or off.
+
As for all PCI devices, you can add bus=PCI-BUS,addr=DEVFN to
control the PCI device address.
@@ -240,6 +243,9 @@ For PCI devices, you can add bus=PCI-BUS,addr=DEVFN to control the PCI
device address, as usual. The old -net nic provides parameter addr
for that, it is silently ignored when the NIC is not a PCI device.
+For virtio-net-pci, you can control whether or not ioeventfd is used for
+virtqueue notify by setting ioeventfd= to on or off (default).
+
-net nic accepts vectors=V for all models, but it's silently ignored
except for virtio-net-pci (model=virtio). With -device, only devices
that support it accept it.
commit 25db9ebe15125deb32958c6df74996f745edf1f9
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date: Fri Dec 17 12:01:50 2010 +0000
virtio-pci: Use ioeventfd for virtqueue notify
Virtqueue notify is currently handled synchronously in userspace virtio. This
prevents the vcpu from executing guest code while hardware emulation code
handles the notify.
On systems that support KVM, the ioeventfd mechanism can be used to make
virtqueue notify a lightweight exit by deferring hardware emulation to the
iothread and allowing the VM to continue execution. This model is similar to
how vhost receives virtqueue notifies.
The result of this change is improved performance for userspace virtio devices.
Virtio-blk throughput increases especially for multithreaded scenarios and
virtio-net transmit throughput increases substantially.
Some virtio devices are known to have guest drivers which expect a notify to be
processed synchronously and spin waiting for completion.
For virtio-net, this also seems to interact with the guest stack in strange
ways so that TCP throughput for small message sizes (~200bytes)
is harmed. Only enable ioeventfd for virtio-blk for now.
Care must be taken not to interfere with vhost-net, which uses host
notifiers. If the set_host_notifier() API is used by a device
virtio-pci will disable virtio-ioeventfd and let the device deal with
host notifiers as it wishes.
Finally, there used to be a limit of 6 KVM io bus devices inside the
kernel. On such a kernel, don't use ioeventfd for virtqueue host
notification since the limit is reached too easily. This ensures that
existing vhost-net setups (which always use ioeventfd) have ioeventfds
available so they can continue to work.
After migration and on VM change state (running/paused) virtio-ioeventfd
will enable/disable itself.
* VIRTIO_CONFIG_S_DRIVER_OK -> enable virtio-ioeventfd
* !VIRTIO_CONFIG_S_DRIVER_OK -> disable virtio-ioeventfd
* virtio_pci_set_host_notifier() -> disable virtio-ioeventfd
* vm_change_state(running=0) -> disable virtio-ioeventfd
* vm_change_state(running=1) -> enable virtio-ioeventfd
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 13dd391..70c40ee 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -83,6 +83,11 @@
/* Flags track per-device state like workarounds for quirks in older guests. */
#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG (1 << 0)
+/* Performance improves when virtqueue kick processing is decoupled from the
+ * vcpu thread using ioeventfd for some devices. */
+#define VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT 1
+#define VIRTIO_PCI_FLAG_USE_IOEVENTFD (1 << VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT)
+
/* QEMU doesn't strictly need write barriers since everything runs in
* lock-step. We'll leave the calls to wmb() in though to make it obvious for
* KVM or if kqemu gets SMP support.
@@ -107,6 +112,8 @@ typedef struct {
/* Max. number of ports we can have for a the virtio-serial device */
uint32_t max_virtserial_ports;
virtio_net_conf net;
+ bool ioeventfd_disabled;
+ bool ioeventfd_started;
} VirtIOPCIProxy;
/* virtio device */
@@ -179,12 +186,132 @@ static int virtio_pci_load_queue(void * opaque, int n, QEMUFile *f)
return 0;
}
+static int virtio_pci_set_host_notifier_internal(VirtIOPCIProxy *proxy,
+ int n, bool assign)
+{
+ VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
+ EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
+ int r;
+ if (assign) {
+ r = event_notifier_init(notifier, 1);
+ if (r < 0) {
+ return r;
+ }
+ r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
+ proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
+ n, assign);
+ if (r < 0) {
+ event_notifier_cleanup(notifier);
+ }
+ } else {
+ r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
+ proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
+ n, assign);
+ if (r < 0) {
+ return r;
+ }
+
+ /* Handle the race condition where the guest kicked and we deassigned
+ * before we got around to handling the kick.
+ */
+ if (event_notifier_test_and_clear(notifier)) {
+ virtio_queue_notify_vq(vq);
+ }
+
+ event_notifier_cleanup(notifier);
+ }
+ return r;
+}
+
+static void virtio_pci_host_notifier_read(void *opaque)
+{
+ VirtQueue *vq = opaque;
+ EventNotifier *n = virtio_queue_get_host_notifier(vq);
+ if (event_notifier_test_and_clear(n)) {
+ virtio_queue_notify_vq(vq);
+ }
+}
+
+static void virtio_pci_set_host_notifier_fd_handler(VirtIOPCIProxy *proxy,
+ int n, bool assign)
+{
+ VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
+ EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
+ if (assign) {
+ qemu_set_fd_handler(event_notifier_get_fd(notifier),
+ virtio_pci_host_notifier_read, NULL, vq);
+ } else {
+ qemu_set_fd_handler(event_notifier_get_fd(notifier),
+ NULL, NULL, NULL);
+ }
+}
+
+static int virtio_pci_start_ioeventfd(VirtIOPCIProxy *proxy)
+{
+ int n, r;
+
+ if (!(proxy->flags & VIRTIO_PCI_FLAG_USE_IOEVENTFD) ||
+ proxy->ioeventfd_disabled ||
+ proxy->ioeventfd_started) {
+ return 0;
+ }
+
+ for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(proxy->vdev, n)) {
+ continue;
+ }
+
+ r = virtio_pci_set_host_notifier_internal(proxy, n, true);
+ if (r < 0) {
+ goto assign_error;
+ }
+
+ virtio_pci_set_host_notifier_fd_handler(proxy, n, true);
+ }
+ proxy->ioeventfd_started = true;
+ return 0;
+
+assign_error:
+ while (--n >= 0) {
+ if (!virtio_queue_get_num(proxy->vdev, n)) {
+ continue;
+ }
+
+ virtio_pci_set_host_notifier_fd_handler(proxy, n, false);
+ virtio_pci_set_host_notifier_internal(proxy, n, false);
+ }
+ proxy->ioeventfd_started = false;
+ proxy->ioeventfd_disabled = true;
+ return r;
+}
+
+static int virtio_pci_stop_ioeventfd(VirtIOPCIProxy *proxy)
+{
+ int n;
+
+ if (!proxy->ioeventfd_started) {
+ return 0;
+ }
+
+ for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(proxy->vdev, n)) {
+ continue;
+ }
+
+ virtio_pci_set_host_notifier_fd_handler(proxy, n, false);
+ virtio_pci_set_host_notifier_internal(proxy, n, false);
+ }
+ proxy->ioeventfd_started = false;
+ return 0;
+}
+
static void virtio_pci_reset(DeviceState *d)
{
VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev);
+ virtio_pci_stop_ioeventfd(proxy);
virtio_reset(proxy->vdev);
msix_reset(&proxy->pci_dev);
- proxy->flags = 0;
+ proxy->flags &= ~VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
}
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
@@ -209,6 +336,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
case VIRTIO_PCI_QUEUE_PFN:
pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
if (pa == 0) {
+ virtio_pci_stop_ioeventfd(proxy);
virtio_reset(proxy->vdev);
msix_unuse_all_vectors(&proxy->pci_dev);
}
@@ -223,7 +351,16 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
virtio_queue_notify(vdev, val);
break;
case VIRTIO_PCI_STATUS:
+ if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) {
+ virtio_pci_stop_ioeventfd(proxy);
+ }
+
virtio_set_status(vdev, val & 0xFF);
+
+ if (val & VIRTIO_CONFIG_S_DRIVER_OK) {
+ virtio_pci_start_ioeventfd(proxy);
+ }
+
if (vdev->status == 0) {
virtio_reset(proxy->vdev);
msix_unuse_all_vectors(&proxy->pci_dev);
@@ -403,6 +540,7 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
if (PCI_COMMAND == address) {
if (!(val & PCI_COMMAND_MASTER)) {
if (!(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
+ virtio_pci_stop_ioeventfd(proxy);
virtio_set_status(proxy->vdev,
proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
}
@@ -480,30 +618,30 @@ assign_error:
static int virtio_pci_set_host_notifier(void *opaque, int n, bool assign)
{
VirtIOPCIProxy *proxy = opaque;
- VirtQueue *vq = virtio_get_queue(proxy->vdev, n);
- EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
- int r;
+
+ /* Stop using ioeventfd for virtqueue kick if the device starts using host
+ * notifiers. This makes it easy to avoid stepping on each others' toes.
+ */
+ proxy->ioeventfd_disabled = assign;
if (assign) {
- r = event_notifier_init(notifier, 1);
- if (r < 0) {
- return r;
- }
- r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
- proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
- n, assign);
- if (r < 0) {
- event_notifier_cleanup(notifier);
- }
+ virtio_pci_stop_ioeventfd(proxy);
+ }
+ /* We don't need to start here: it's not needed because backend
+ * currently only stops on status change away from ok,
+ * reset, vmstop and such. If we do add code to start here,
+ * need to check vmstate, device state etc. */
+ return virtio_pci_set_host_notifier_internal(proxy, n, assign);
+}
+
+static void virtio_pci_vmstate_change(void *opaque, bool running)
+{
+ VirtIOPCIProxy *proxy = opaque;
+
+ if (running) {
+ virtio_pci_start_ioeventfd(proxy);
} else {
- r = kvm_set_ioeventfd_pio_word(event_notifier_get_fd(notifier),
- proxy->addr + VIRTIO_PCI_QUEUE_NOTIFY,
- n, assign);
- if (r < 0) {
- return r;
- }
- event_notifier_cleanup(notifier);
+ virtio_pci_stop_ioeventfd(proxy);
}
- return r;
}
static const VirtIOBindings virtio_pci_bindings = {
@@ -515,6 +653,7 @@ static const VirtIOBindings virtio_pci_bindings = {
.get_features = virtio_pci_get_features,
.set_host_notifier = virtio_pci_set_host_notifier,
.set_guest_notifiers = virtio_pci_set_guest_notifiers,
+ .vmstate_change = virtio_pci_vmstate_change,
};
static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
@@ -559,10 +698,15 @@ static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
pci_register_bar(&proxy->pci_dev, 0, size, PCI_BASE_ADDRESS_SPACE_IO,
virtio_map);
+ if (!kvm_has_many_ioeventfds()) {
+ proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD;
+ }
+
virtio_bind_device(vdev, &virtio_pci_bindings, proxy);
proxy->host_features |= 0x1 << VIRTIO_F_NOTIFY_ON_EMPTY;
proxy->host_features |= 0x1 << VIRTIO_F_BAD_FEATURE;
proxy->host_features = vdev->get_features(vdev, proxy->host_features);
+
}
static int virtio_blk_init_pci(PCIDevice *pci_dev)
@@ -597,6 +741,7 @@ static int virtio_blk_exit_pci(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+ virtio_pci_stop_ioeventfd(proxy);
virtio_blk_exit(proxy->vdev);
blockdev_mark_auto_del(proxy->block.bs);
return virtio_exit_pci(pci_dev);
@@ -658,6 +803,7 @@ static int virtio_net_exit_pci(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+ virtio_pci_stop_ioeventfd(proxy);
virtio_net_exit(proxy->vdev);
return virtio_exit_pci(pci_dev);
}
@@ -705,6 +851,8 @@ static PCIDeviceInfo virtio_info[] = {
.qdev.props = (Property[]) {
DEFINE_PROP_HEX32("class", VirtIOPCIProxy, class_code, 0),
DEFINE_BLOCK_PROPERTIES(VirtIOPCIProxy, block),
+ DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
+ VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_PROP_END_OF_LIST(),
@@ -717,6 +865,8 @@ static PCIDeviceInfo virtio_info[] = {
.exit = virtio_net_exit_pci,
.romfile = "pxe-virtio.bin",
.qdev.props = (Property[]) {
+ DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
+ VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
diff --git a/hw/virtio.c b/hw/virtio.c
index 1d20be2..31bd9e3 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -575,11 +575,19 @@ int virtio_queue_get_num(VirtIODevice *vdev, int n)
return vdev->vq[n].vring.num;
}
+void virtio_queue_notify_vq(VirtQueue *vq)
+{
+ if (vq->vring.desc) {
+ VirtIODevice *vdev = vq->vdev;
+ trace_virtio_queue_notify(vdev, vq - vdev->vq, vq);
+ vq->handle_output(vdev, vq);
+ }
+}
+
void virtio_queue_notify(VirtIODevice *vdev, int n)
{
- if (n < VIRTIO_PCI_QUEUE_MAX && vdev->vq[n].vring.desc) {
- trace_virtio_queue_notify(vdev, n, &vdev->vq[n]);
- vdev->vq[n].handle_output(vdev, &vdev->vq[n]);
+ if (n < VIRTIO_PCI_QUEUE_MAX) {
+ virtio_queue_notify_vq(&vdev->vq[n]);
}
}
diff --git a/hw/virtio.h b/hw/virtio.h
index bd52742..d8546d5 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -222,5 +222,6 @@ void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n, uint16_t idx);
VirtQueue *virtio_get_queue(VirtIODevice *vdev, int n);
EventNotifier *virtio_queue_get_guest_notifier(VirtQueue *vq);
EventNotifier *virtio_queue_get_host_notifier(VirtQueue *vq);
+void virtio_queue_notify_vq(VirtQueue *vq);
void virtio_irq(VirtQueue *vq);
#endif
commit d2f2b8a740c82319f9eea51ebed50815fbc3da3e
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date: Mon Jan 10 13:50:05 2011 +0200
kvm: test for ioeventfd support on old kernels
There used to be a limit of 6 KVM io bus devices in the kernel.
On such a kernel, we can't use many ioeventfds for host notification
since the limit is reached too easily.
Add an API to test for this condition.
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/kvm-all.c b/kvm-all.c
index cae24bb..255b6fa 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -28,6 +28,11 @@
#include "kvm.h"
#include "bswap.h"
+/* This check must be after config-host.h is included */
+#ifdef CONFIG_EVENTFD
+#include <sys/eventfd.h>
+#endif
+
/* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
#define PAGE_SIZE TARGET_PAGE_SIZE
@@ -72,6 +77,7 @@ struct KVMState
int irqchip_in_kernel;
int pit_in_kernel;
int xsave, xcrs;
+ int many_ioeventfds;
};
static KVMState *kvm_state;
@@ -441,6 +447,39 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
return ret;
}
+static int kvm_check_many_ioeventfds(void)
+{
+ /* Older kernels have a 6 device limit on the KVM io bus. Find out so we
+ * can avoid creating too many ioeventfds.
+ */
+#ifdef CONFIG_EVENTFD
+ int ioeventfds[7];
+ int i, ret = 0;
+ for (i = 0; i < ARRAY_SIZE(ioeventfds); i++) {
+ ioeventfds[i] = eventfd(0, EFD_CLOEXEC);
+ if (ioeventfds[i] < 0) {
+ break;
+ }
+ ret = kvm_set_ioeventfd_pio_word(ioeventfds[i], 0, i, true);
+ if (ret < 0) {
+ close(ioeventfds[i]);
+ break;
+ }
+ }
+
+ /* Decide whether many devices are supported or not */
+ ret = i == ARRAY_SIZE(ioeventfds);
+
+ while (i-- > 0) {
+ kvm_set_ioeventfd_pio_word(ioeventfds[i], 0, i, false);
+ close(ioeventfds[i]);
+ }
+ return ret;
+#else
+ return 0;
+#endif
+}
+
static void kvm_set_phys_mem(target_phys_addr_t start_addr,
ram_addr_t size,
ram_addr_t phys_offset)
@@ -717,6 +756,8 @@ int kvm_init(int smp_cpus)
kvm_state = s;
cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client);
+ s->many_ioeventfds = kvm_check_many_ioeventfds();
+
return 0;
err:
@@ -1046,6 +1087,14 @@ int kvm_has_xcrs(void)
return kvm_state->xcrs;
}
+int kvm_has_many_ioeventfds(void)
+{
+ if (!kvm_enabled()) {
+ return 0;
+ }
+ return kvm_state->many_ioeventfds;
+}
+
void kvm_setup_guest_memory(void *start, size_t size)
{
if (!kvm_has_sync_mmu()) {
diff --git a/kvm-stub.c b/kvm-stub.c
index 5384a4b..33d4476 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -99,6 +99,11 @@ int kvm_has_robust_singlestep(void)
return 0;
}
+int kvm_has_many_ioeventfds(void)
+{
+ return 0;
+}
+
void kvm_setup_guest_memory(void *start, size_t size)
{
}
diff --git a/kvm.h b/kvm.h
index 60a9b42..ce08d42 100644
--- a/kvm.h
+++ b/kvm.h
@@ -42,6 +42,7 @@ int kvm_has_robust_singlestep(void);
int kvm_has_debugregs(void);
int kvm_has_xsave(void);
int kvm_has_xcrs(void);
+int kvm_has_many_ioeventfds(void);
#ifdef NEED_CPU_H
int kvm_init_vcpu(CPUState *env);
commit 85cf2a8d7435754f685a26f95dcb43a93a84ff60
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Mon Jan 10 14:28:40 2011 +0200
virtio: move vmstate change tracking to core
Move tracking vmstate change from virtio-net to virtio.c
as it is going to be used by virito-blk and virtio-pci
for the ioeventfd support.
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index ec1bf8d..ccb3e63 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -54,8 +54,6 @@ typedef struct VirtIONet
uint8_t nouni;
uint8_t nobcast;
uint8_t vhost_started;
- bool vm_running;
- VMChangeStateEntry *vmstate;
struct {
int in_use;
int first_multi;
@@ -102,7 +100,7 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
static bool virtio_net_started(VirtIONet *n, uint8_t status)
{
return (status & VIRTIO_CONFIG_S_DRIVER_OK) &&
- (n->status & VIRTIO_NET_S_LINK_UP) && n->vm_running;
+ (n->status & VIRTIO_NET_S_LINK_UP) && n->vdev.vm_running;
}
static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
@@ -453,7 +451,7 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
static int virtio_net_can_receive(VLANClientState *nc)
{
VirtIONet *n = DO_UPCAST(NICState, nc, nc)->opaque;
- if (!n->vm_running) {
+ if (!n->vdev.vm_running) {
return 0;
}
@@ -708,7 +706,7 @@ static int32_t virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
return num_packets;
}
- assert(n->vm_running);
+ assert(n->vdev.vm_running);
if (n->async_tx.elem.out_num) {
virtio_queue_set_notification(n->tx_vq, 0);
@@ -769,7 +767,7 @@ static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq)
VirtIONet *n = to_virtio_net(vdev);
/* This happens when device was stopped but VCPU wasn't. */
- if (!n->vm_running) {
+ if (!n->vdev.vm_running) {
n->tx_waiting = 1;
return;
}
@@ -796,7 +794,7 @@ static void virtio_net_handle_tx_bh(VirtIODevice *vdev, VirtQueue *vq)
}
n->tx_waiting = 1;
/* This happens when device was stopped but VCPU wasn't. */
- if (!n->vm_running) {
+ if (!n->vdev.vm_running) {
return;
}
virtio_queue_set_notification(vq, 0);
@@ -806,7 +804,7 @@ static void virtio_net_handle_tx_bh(VirtIODevice *vdev, VirtQueue *vq)
static void virtio_net_tx_timer(void *opaque)
{
VirtIONet *n = opaque;
- assert(n->vm_running);
+ assert(n->vdev.vm_running);
n->tx_waiting = 0;
@@ -823,7 +821,7 @@ static void virtio_net_tx_bh(void *opaque)
VirtIONet *n = opaque;
int32_t ret;
- assert(n->vm_running);
+ assert(n->vdev.vm_running);
n->tx_waiting = 0;
@@ -988,16 +986,6 @@ static NetClientInfo net_virtio_info = {
.link_status_changed = virtio_net_set_link_status,
};
-static void virtio_net_vmstate_change(void *opaque, int running, int reason)
-{
- VirtIONet *n = opaque;
- n->vm_running = running;
- /* This is called when vm is started/stopped,
- * it will start/stop vhost backend if appropriate
- * e.g. after migration. */
- virtio_net_set_status(&n->vdev, n->vdev.status);
-}
-
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
virtio_net_conf *net)
{
@@ -1052,7 +1040,6 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
n->qdev = dev;
register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
virtio_net_save, virtio_net_load, n);
- n->vmstate = qemu_add_vm_change_state_handler(virtio_net_vmstate_change, n);
add_boot_device_path(conf->bootindex, dev, "/ethernet-phy at 0");
@@ -1062,7 +1049,6 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
void virtio_net_exit(VirtIODevice *vdev)
{
VirtIONet *n = DO_UPCAST(VirtIONet, vdev, vdev);
- qemu_del_vm_change_state_handler(n->vmstate);
/* This will stop vhost backend if appropriate. */
virtio_net_set_status(vdev, 0);
diff --git a/hw/virtio.c b/hw/virtio.c
index 07dbf86..1d20be2 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -743,11 +743,31 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
void virtio_cleanup(VirtIODevice *vdev)
{
+ qemu_del_vm_change_state_handler(vdev->vmstate);
if (vdev->config)
qemu_free(vdev->config);
qemu_free(vdev->vq);
}
+static void virtio_vmstate_change(void *opaque, int running, int reason)
+{
+ VirtIODevice *vdev = opaque;
+ bool backend_run = running && (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK);
+ vdev->vm_running = running;
+
+ if (backend_run) {
+ virtio_set_status(vdev, vdev->status);
+ }
+
+ if (vdev->binding->vmstate_change) {
+ vdev->binding->vmstate_change(vdev->binding_opaque, backend_run);
+ }
+
+ if (!backend_run) {
+ virtio_set_status(vdev, vdev->status);
+ }
+}
+
VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
size_t config_size, size_t struct_size)
{
@@ -774,6 +794,8 @@ VirtIODevice *virtio_common_init(const char *name, uint16_t device_id,
else
vdev->config = NULL;
+ vdev->vmstate = qemu_add_vm_change_state_handler(virtio_vmstate_change, vdev);
+
return vdev;
}
diff --git a/hw/virtio.h b/hw/virtio.h
index 02fa312..bd52742 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -95,6 +95,7 @@ typedef struct {
unsigned (*get_features)(void * opaque);
int (*set_guest_notifiers)(void * opaque, bool assigned);
int (*set_host_notifier)(void * opaque, int n, bool assigned);
+ void (*vmstate_change)(void * opaque, bool running);
} VirtIOBindings;
#define VIRTIO_PCI_QUEUE_MAX 64
@@ -123,6 +124,8 @@ struct VirtIODevice
const VirtIOBindings *binding;
void *binding_opaque;
uint16_t device_id;
+ bool vm_running;
+ VMChangeStateEntry *vmstate;
};
static inline void virtio_set_status(VirtIODevice *vdev, uint8_t val)
commit 3dbca8e6a7a5be52c3251ad03bf30d73301babf3
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date: Fri Dec 17 12:01:49 2010 +0000
virtio-pci: Rename bugs field to flags
The VirtIOPCIProxy bugs field is currently used to enable workarounds
for older guests. Rename it to flags so that other per-device behavior
can be tracked.
A later patch uses the flags field to remember whether ioeventfd should
be used for virtqueue host notification.
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 6186142..13dd391 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -80,9 +80,8 @@
* 12 is historical, and due to x86 page size. */
#define VIRTIO_PCI_QUEUE_ADDR_SHIFT 12
-/* We can catch some guest bugs inside here so we continue supporting older
- guests. */
-#define VIRTIO_PCI_BUG_BUS_MASTER (1 << 0)
+/* Flags track per-device state like workarounds for quirks in older guests. */
+#define VIRTIO_PCI_FLAG_BUS_MASTER_BUG (1 << 0)
/* QEMU doesn't strictly need write barriers since everything runs in
* lock-step. We'll leave the calls to wmb() in though to make it obvious for
@@ -95,7 +94,7 @@
typedef struct {
PCIDevice pci_dev;
VirtIODevice *vdev;
- uint32_t bugs;
+ uint32_t flags;
uint32_t addr;
uint32_t class_code;
uint32_t nvectors;
@@ -159,7 +158,7 @@ static int virtio_pci_load_config(void * opaque, QEMUFile *f)
in ready state. Then we have a buggy guest OS. */
if ((proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
!(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
- proxy->bugs |= VIRTIO_PCI_BUG_BUS_MASTER;
+ proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
}
return 0;
}
@@ -185,7 +184,7 @@ static void virtio_pci_reset(DeviceState *d)
VirtIOPCIProxy *proxy = container_of(d, VirtIOPCIProxy, pci_dev.qdev);
virtio_reset(proxy->vdev);
msix_reset(&proxy->pci_dev);
- proxy->bugs = 0;
+ proxy->flags = 0;
}
static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
@@ -235,7 +234,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
some safety checks. */
if ((val & VIRTIO_CONFIG_S_DRIVER_OK) &&
!(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
- proxy->bugs |= VIRTIO_PCI_BUG_BUS_MASTER;
+ proxy->flags |= VIRTIO_PCI_FLAG_BUS_MASTER_BUG;
}
break;
case VIRTIO_MSI_CONFIG_VECTOR:
@@ -403,7 +402,7 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
if (PCI_COMMAND == address) {
if (!(val & PCI_COMMAND_MASTER)) {
- if (!(proxy->bugs & VIRTIO_PCI_BUG_BUS_MASTER)) {
+ if (!(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
virtio_set_status(proxy->vdev,
proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
}
commit 2f6bfe3b0c5bb216abfe015d824eaf84c449c6a5
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Thu Jan 6 15:14:40 2011 +0100
qxl: tag as not hotpluggable
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/qxl.c b/hw/qxl.c
index 207aa63..bd71e58 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1546,6 +1546,7 @@ static PCIDeviceInfo qxl_info_primary = {
.qdev.size = sizeof(PCIQXLDevice),
.qdev.reset = qxl_reset_handler,
.qdev.vmsd = &qxl_vmstate,
+ .no_hotplug = 1,
.init = qxl_init_primary,
.config_write = qxl_write_config,
.romfile = "vgabios-qxl.bin",
commit 6107ff12922e5508a44b376b40a3041810cb00d2
Merge: be92bbf... 8aaf42e...
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Mon Jan 10 13:43:48 2011 +0200
Merge remote branch 'origin/master' into pci
commit be92bbf73dfd7d8a4786dc5f6c71590f4fbc5a32
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Thu Jan 6 15:14:39 2011 +0100
vga: tag as not hotplugable.
This patch tags all vga cards as not hotpluggable. The qemu
standard vga will never ever be hotpluggable. For cirrus + vmware
it might be possible to get that work some day. Todays we can't
handle that for a number of reasons though.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 4f5040c..0d522a0 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3227,6 +3227,7 @@ static PCIDeviceInfo cirrus_vga_info = {
.qdev.desc = "Cirrus CLGD 54xx VGA",
.qdev.size = sizeof(PCICirrusVGAState),
.qdev.vmsd = &vmstate_pci_cirrus_vga,
+ .no_hotplug = 1,
.init = pci_cirrus_vga_initfn,
.romfile = VGABIOS_CIRRUS_FILENAME,
.config_write = pci_cirrus_write_config,
diff --git a/hw/vga-pci.c b/hw/vga-pci.c
index 791ca22..ce9ec45 100644
--- a/hw/vga-pci.c
+++ b/hw/vga-pci.c
@@ -110,6 +110,7 @@ static PCIDeviceInfo vga_info = {
.qdev.name = "VGA",
.qdev.size = sizeof(PCIVGAState),
.qdev.vmsd = &vmstate_vga_pci,
+ .no_hotplug = 1,
.init = pci_vga_initfn,
.config_write = pci_vga_write_config,
.romfile = "vgabios-stdvga.bin",
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index d9dd52f..6c59053 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1318,6 +1318,7 @@ static PCIDeviceInfo vmsvga_info = {
.qdev.name = "vmware-svga",
.qdev.size = sizeof(struct pci_vmsvga_state_s),
.qdev.vmsd = &vmstate_vmware_vga,
+ .no_hotplug = 1,
.init = pci_vmsvga_initfn,
.romfile = "vgabios-vmware.bin",
};
commit 0965f12da61cbfe62252d21a8e6fa309753760e8
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Thu Jan 6 15:14:38 2011 +0100
piix: tag as not hotpluggable.
This patch tags all pci devices which belong to the piix3/4 chipsets as
not hotpluggable (Host bridge, ISA bridge, IDE controller, ACPI bridge).
Acked-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 173d781..273097d 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -428,6 +428,8 @@ static PCIDeviceInfo piix4_pm_info = {
.qdev.desc = "PM",
.qdev.size = sizeof(PIIX4PMState),
.qdev.vmsd = &vmstate_acpi,
+ .qdev.no_user = 1,
+ .no_hotplug = 1,
.init = piix4_pm_initfn,
.config_write = pm_write_config,
.qdev.props = (Property[]) {
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 1cad906..d4289af 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -194,11 +194,13 @@ static PCIDeviceInfo piix_ide_info[] = {
.qdev.name = "piix3-ide",
.qdev.size = sizeof(PCIIDEState),
.qdev.no_user = 1,
+ .no_hotplug = 1,
.init = pci_piix3_ide_initfn,
},{
.qdev.name = "piix4-ide",
.qdev.size = sizeof(PCIIDEState),
.qdev.no_user = 1,
+ .no_hotplug = 1,
.init = pci_piix4_ide_initfn,
},{
/* end of list */
diff --git a/hw/piix4.c b/hw/piix4.c
index 5489386..72073cd 100644
--- a/hw/piix4.c
+++ b/hw/piix4.c
@@ -113,6 +113,7 @@ static PCIDeviceInfo piix4_info[] = {
.qdev.desc = "ISA bridge",
.qdev.size = sizeof(PCIDevice),
.qdev.no_user = 1,
+ .no_hotplug = 1,
.init = piix4_initfn,
},{
/* end of list */
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index 38f9d9e..358da58 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -348,6 +348,7 @@ static PCIDeviceInfo i440fx_info[] = {
.qdev.size = sizeof(PCII440FXState),
.qdev.vmsd = &vmstate_i440fx,
.qdev.no_user = 1,
+ .no_hotplug = 1,
.init = i440fx_initfn,
.config_write = i440fx_write_config,
},{
@@ -356,6 +357,7 @@ static PCIDeviceInfo i440fx_info[] = {
.qdev.size = sizeof(PIIX3State),
.qdev.vmsd = &vmstate_piix3,
.qdev.no_user = 1,
+ .no_hotplug = 1,
.init = piix3_initfn,
},{
/* end of list */
commit 180c22e18b0a9be21445271f94347238b0bc0a25
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Thu Jan 6 15:14:37 2011 +0100
pci: allow devices being tagged as not hotpluggable.
This patch adds a field to PCIDeviceInfo to tag devices as being
not hotpluggable. Any attempt to plug-in or -out such a device
will throw an error.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/pci.c b/hw/pci.c
index d0b51b8..8d0e3df 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1624,6 +1624,11 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
info->is_bridge);
if (pci_dev == NULL)
return -1;
+ if (qdev->hotplugged && info->no_hotplug) {
+ qerror_report(QERR_DEVICE_NO_HOTPLUG, info->qdev.name);
+ do_pci_unregister_device(pci_dev);
+ return -1;
+ }
rc = info->init(pci_dev);
if (rc != 0) {
do_pci_unregister_device(pci_dev);
@@ -1656,7 +1661,12 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
static int pci_unplug_device(DeviceState *qdev)
{
PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
+ PCIDeviceInfo *info = container_of(qdev->info, PCIDeviceInfo, qdev);
+ if (info->no_hotplug) {
+ qerror_report(QERR_DEVICE_NO_HOTPLUG, info->qdev.name);
+ return -1;
+ }
return dev->bus->hotplug(dev->bus->hotplug_qdev, dev,
PCI_HOTPLUG_DISABLED);
}
diff --git a/hw/pci.h b/hw/pci.h
index 052960e..bc8d5bb 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -436,6 +436,9 @@ typedef struct {
/* pcie stuff */
int is_express; /* is this device pci express? */
+ /* device isn't hot-pluggable */
+ int no_hotplug;
+
/* rom bar */
const char *romfile;
} PCIDeviceInfo;
diff --git a/qerror.c b/qerror.c
index ac2cdaf..9d0cdeb 100644
--- a/qerror.c
+++ b/qerror.c
@@ -101,6 +101,10 @@ static const QErrorStringTable qerror_table[] = {
.desc = "Device '%(device)' has no child bus",
},
{
+ .error_fmt = QERR_DEVICE_NO_HOTPLUG,
+ .desc = "Device '%(device)' does not support hotplugging",
+ },
+ {
.error_fmt = QERR_DUPLICATE_ID,
.desc = "Duplicate ID '%(id)' for %(object)",
},
diff --git a/qerror.h b/qerror.h
index 943a24b..b0f69da 100644
--- a/qerror.h
+++ b/qerror.h
@@ -90,6 +90,9 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_DEVICE_NO_BUS \
"{ 'class': 'DeviceNoBus', 'data': { 'device': %s } }"
+#define QERR_DEVICE_NO_HOTPLUG \
+ "{ 'class': 'DeviceNoHotplug', 'data': { 'device': %s } }"
+
#define QERR_DUPLICATE_ID \
"{ 'class': 'DuplicateId', 'data': { 'id': %s, 'object': %s } }"
commit c574ba5a4ce0faee6a687412804d6045ef815327
Author: Alex Williamson <alex.williamson at redhat.com>
Date: Tue Jan 4 12:38:02 2011 -0700
rtl8139: Use subsection to restrict migration after hotplug
rtl8139 includes a cpu_register_io_memory acquired value in it's
migration data. This is not only unecessary, but we should treat
these values as unique to the VM instances since the value depends
on call order. In most cases, this miraculously still works.
However, if devices are added or removed from the system, it may
represent an ordering change, which could cause the target rtl8139
device to make use of another device's cpu_register_io_memory value.
If we detect that a hot-add/remove has occured, include a subsection
to restrict migrations only to driver versions known to include this
fix.
Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
Acked-by: Michael S. Tsirkin <mst at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/rtl8139.c b/hw/rtl8139.c
index a8aed89..a22530c 100644
--- a/hw/rtl8139.c
+++ b/hw/rtl8139.c
@@ -495,6 +495,8 @@ typedef struct RTL8139State {
QEMUTimer *timer;
int64_t TimerExpire;
+ /* Support migration to/from old versions */
+ int rtl8139_mmio_io_addr_dummy;
} RTL8139State;
static void rtl8139_set_next_tctr_time(RTL8139State *s, int64_t current_time);
@@ -3162,6 +3164,21 @@ static int rtl8139_post_load(void *opaque, int version_id)
return 0;
}
+static bool rtl8139_hotplug_ready_needed(void *opaque)
+{
+ return qdev_machine_modified();
+}
+
+static const VMStateDescription vmstate_rtl8139_hotplug_ready ={
+ .name = "rtl8139/hotplug_ready",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static void rtl8139_pre_save(void *opaque)
{
RTL8139State* s = opaque;
@@ -3171,6 +3188,7 @@ static void rtl8139_pre_save(void *opaque)
rtl8139_set_next_tctr_time(s, current_time);
s->TCTR = muldiv64(current_time - s->TCTR_base, PCI_FREQUENCY,
get_ticks_per_sec());
+ s->rtl8139_mmio_io_addr_dummy = s->rtl8139_mmio_io_addr;
}
static const VMStateDescription vmstate_rtl8139 = {
@@ -3223,7 +3241,7 @@ static const VMStateDescription vmstate_rtl8139 = {
VMSTATE_UNUSED(4),
VMSTATE_MACADDR(conf.macaddr, RTL8139State),
- VMSTATE_INT32(rtl8139_mmio_io_addr, RTL8139State),
+ VMSTATE_INT32(rtl8139_mmio_io_addr_dummy, RTL8139State),
VMSTATE_UINT32(currTxDesc, RTL8139State),
VMSTATE_UINT32(currCPlusRxDesc, RTL8139State),
@@ -3252,6 +3270,14 @@ static const VMStateDescription vmstate_rtl8139 = {
VMSTATE_UINT32_V(cplus_enabled, RTL8139State, 4),
VMSTATE_END_OF_LIST()
+ },
+ .subsections = (VMStateSubsection []) {
+ {
+ .vmsd = &vmstate_rtl8139_hotplug_ready,
+ .needed = rtl8139_hotplug_ready_needed,
+ }, {
+ /* empty */
+ }
}
};
commit 0ac8ef71329ee242951074eb2dc7136f99421d8c
Author: Alex Williamson <alex.williamson at redhat.com>
Date: Tue Jan 4 12:37:50 2011 -0700
qdev: Track runtime machine modifications
Create a trivial interface to track whether the machine has been
modified since boot. Adding or removing devices will trigger this
to return true. An example usage scenario for such an interface is
the rtl8139 driver which includes a cpu_register_io_memory() value
in it's migration stream. For the majority of migrations, where
no hotplug has occured in the machine, this works correctly. Once
the machine is modified, we can use this interface to detect that
and include a subsection for the device to prevent migrations to
rtl8139 versions with this bug.
Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
Acked-by: Michael S. Tsirkin <mst at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/qdev.c b/hw/qdev.c
index 31eb464..5b8d374 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -32,6 +32,8 @@
#include "blockdev.h"
static int qdev_hotplug = 0;
+static bool qdev_hot_added = false;
+static bool qdev_hot_removed = false;
/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
static BusState *main_system_bus;
@@ -93,6 +95,7 @@ static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
if (qdev_hotplug) {
assert(bus->allow_hotplug);
dev->hotplugged = 1;
+ qdev_hot_added = true;
}
dev->instance_id_alias = -1;
dev->state = DEV_STATE_CREATED;
@@ -294,6 +297,8 @@ int qdev_unplug(DeviceState *dev)
}
assert(dev->info->unplug != NULL);
+ qdev_hot_removed = true;
+
return dev->info->unplug(dev);
}
@@ -395,6 +400,11 @@ void qdev_machine_creation_done(void)
qdev_hotplug = 1;
}
+bool qdev_machine_modified(void)
+{
+ return qdev_hot_added || qdev_hot_removed;
+}
+
/* Get a character (serial) device interface. */
CharDriverState *qdev_init_chardev(DeviceState *dev)
{
diff --git a/hw/qdev.h b/hw/qdev.h
index 2be775f..e520aaa 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -132,6 +132,7 @@ int qdev_unplug(DeviceState *dev);
void qdev_free(DeviceState *dev);
int qdev_simple_unplug_cb(DeviceState *dev);
void qdev_machine_creation_done(void);
+bool qdev_machine_modified(void);
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
More information about the Spice-commits
mailing list