Also drop duplicate occurrence of device-hotplug.o.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
libobj-y += disas.o
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
+obj-y += target-$(TARGET_BASE_ARCH)/
+
tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci
# HELPER_CFLAGS is used for all the legacy code compiled with static register
obj-y += linux-user/
obj-y += gdbstub.o thunk.o user-exec.o $(oslib-obj-y)
-obj-i386-y += ioport-user.o
-obj-$(TARGET_ARM) += arm-semi.o
-obj-$(TARGET_M68K) += m68k-semi.o
obj-y += $(addprefix ../, $(universal-obj-y))
obj-y += $(addprefix ../libuser/, $(user-obj-y))
obj-y += bsd-user/
obj-y += gdbstub.o user-exec.o
-obj-i386-y += ioport-user.o
obj-y += $(addprefix ../, $(universal-obj-y))
obj-y += $(addprefix ../libuser/, $(user-obj-y))
# System emulator target
ifdef CONFIG_SOFTMMU
-obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o
+obj-y += arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o ioport.o
# virtio has to be here due to weird dependency between PCI and virtio-net.
# need to fix this properly
obj-$(CONFIG_NO_PCI) += pci-stub.o
obj-$(CONFIG_HAVE_CORE_DUMP) += arch_dump.o
LIBS+=-lz
-obj-i386-$(CONFIG_KVM) += hyperv.o
-
QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
obj-$(CONFIG_NO_XEN) += xen-stub.o
-obj-i386-$(CONFIG_XEN) += xen_platform.o xen_apic.o
-
# Inter-VM PCI shared memory
CONFIG_IVSHMEM =
ifeq ($(CONFIG_KVM), y)
obj-y += device-hotplug.o
# Hardware support
-obj-i386-y += mc146818rtc.o pc.o
-obj-i386-y += apic_common.o apic.o kvmvapic.o
-obj-i386-y += sga.o ioapic_common.o ioapic.o piix_pci.o
-obj-i386-y += vmport.o
-obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
-obj-i386-y += debugcon.o multiboot.o
-obj-i386-y += pc_piix.o
-obj-i386-y += pc_sysfw.o
-obj-i386-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o kvm/i8259.o kvm/ioapic.o kvm/i8254.o
-obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
-
-# shared objects
-obj-ppc-y = ppc.o ppc_booke.o
-# PREP target
-obj-ppc-y += mc146818rtc.o
-obj-ppc-y += ppc_prep.o
-# OldWorld PowerMac
-obj-ppc-y += ppc_oldworld.o
-# NewWorld PowerMac
-obj-ppc-y += ppc_newworld.o
-# IBM pSeries (sPAPR)
-obj-ppc-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
-obj-ppc-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
-obj-ppc-$(CONFIG_PSERIES) += spapr_pci.o device-hotplug.o pci-hotplug.o
-# PowerPC 4xx boards
-obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
-obj-ppc-y += ppc440_bamboo.o
-# PowerPC E500 boards
-obj-ppc-y += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o
-# PowerPC 440 Xilinx ML507 reference board.
-obj-ppc-y += virtex_ml507.o
-obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
-obj-ppc-$(CONFIG_FDT) += device_tree.o
-# PowerPC OpenPIC
-obj-ppc-y += openpic.o
-
-# Xilinx PPC peripherals
-obj-ppc-y += xilinx_intc.o
-obj-ppc-y += xilinx_timer.o
-obj-ppc-y += xilinx_uartlite.o
-obj-ppc-y += xilinx_ethlite.o
-
-# LM32 boards
-obj-lm32-y += lm32_boards.o
-obj-lm32-y += milkymist.o
-
-# LM32 peripherals
-obj-lm32-y += lm32_pic.o
-obj-lm32-y += lm32_juart.o
-obj-lm32-y += lm32_timer.o
-obj-lm32-y += lm32_uart.o
-obj-lm32-y += lm32_sys.o
-obj-lm32-y += milkymist-ac97.o
-obj-lm32-y += milkymist-hpdmc.o
-obj-lm32-y += milkymist-memcard.o
-obj-lm32-y += milkymist-minimac2.o
-obj-lm32-y += milkymist-pfpu.o
-obj-lm32-y += milkymist-softusb.o
-obj-lm32-y += milkymist-sysctl.o
-obj-lm32-$(CONFIG_OPENGL) += milkymist-tmu2.o
-obj-lm32-y += milkymist-uart.o
-obj-lm32-y += milkymist-vgafb.o
-obj-lm32-y += framebuffer.o
-
-obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
-obj-mips-y += mips_addr.o mips_timer.o mips_int.o
-obj-mips-y += gt64xxx.o mc146818rtc.o
-obj-mips-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
-
-obj-microblaze-y = petalogix_s3adsp1800_mmu.o
-obj-microblaze-y += petalogix_ml605_mmu.o
-obj-microblaze-y += microblaze_boot.o
-
-obj-microblaze-y += microblaze_pic_cpu.o
-obj-microblaze-y += xilinx_intc.o
-obj-microblaze-y += xilinx_timer.o
-obj-microblaze-y += xilinx_uartlite.o
-obj-microblaze-y += xilinx_ethlite.o
-obj-microblaze-y += xilinx_axidma.o
-obj-microblaze-y += xilinx_axienet.o
-
-obj-microblaze-$(CONFIG_FDT) += device_tree.o
-
-# Boards
-obj-cris-y = cris_pic_cpu.o
-obj-cris-y += cris-boot.o
-obj-cris-y += axis_dev88.o
-
-# IO blocks
-obj-cris-y += etraxfs_dma.o
-obj-cris-y += etraxfs_pic.o
-obj-cris-y += etraxfs_eth.o
-obj-cris-y += etraxfs_timer.o
-obj-cris-y += etraxfs_ser.o
-
ifeq ($(TARGET_ARCH), sparc64)
-obj-sparc-y = sun4u.o apb_pci.o
-obj-sparc-y += mc146818rtc.o
+obj-y += hw/sparc64/
else
-obj-sparc-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o
-obj-sparc-y += slavio_timer.o slavio_misc.o sparc32_dma.o
-obj-sparc-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o
-
-# GRLIB
-obj-sparc-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o
+obj-y += hw/$(TARGET_BASE_ARCH)/
endif
-obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
-obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
-obj-arm-y += versatile_pci.o
-obj-arm-y += versatile_i2c.o
-obj-arm-y += cadence_uart.o
-obj-arm-y += cadence_ttc.o
-obj-arm-y += cadence_gem.o
-obj-arm-y += xilinx_zynq.o zynq_slcr.o
-obj-arm-y += arm_gic.o
-obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
-obj-arm-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
-obj-arm-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
-obj-arm-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o
-obj-arm-y += arm_l2x0.o
-obj-arm-y += arm_mptimer.o a15mpcore.o
-obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
-obj-arm-y += highbank.o
-obj-arm-y += pl061.o
-obj-arm-y += xgmac.o
-obj-arm-y += arm-semi.o
-obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
-obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
-obj-arm-y += gumstix.o
-obj-arm-y += zaurus.o ide/microdrive.o spitz.o tosa.o tc6393xb.o
-obj-arm-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
- omap_gpio.o omap_intc.o omap_uart.o
-obj-arm-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
- omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
-obj-arm-y += omap_sx1.o palm.o tsc210x.o
-obj-arm-y += nseries.o blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
-obj-arm-y += mst_fpga.o mainstone.o
-obj-arm-y += z2.o
-obj-arm-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
-obj-arm-y += framebuffer.o
-obj-arm-y += vexpress.o
-obj-arm-y += strongarm.o
-obj-arm-y += collie.o
-obj-arm-y += pl041.o lm4549.o
-obj-arm-$(CONFIG_FDT) += device_tree.o
-
-obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
-obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
-obj-sh4-y += ide/mmio.o
-
-obj-m68k-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
-obj-m68k-y += m68k-semi.o dummy_m68k.o
-
-obj-s390x-y = s390-virtio-bus.o s390-virtio.o
-
-obj-alpha-y = mc146818rtc.o
-obj-alpha-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
-
-obj-xtensa-y += xtensa_pic.o
-obj-xtensa-y += xtensa_sim.o
-obj-xtensa-y += xtensa_lx60.o
-obj-xtensa-y += xtensa-semi.o
-obj-xtensa-y += core-dc232b.o
-obj-xtensa-y += core-dc233c.o
-obj-xtensa-y += core-fsf.o
+# Device tree
+ifeq ($(CONFIG_FDT), y)
+obj-$(TARGET_ARM) += device_tree.o
+obj-$(TARGET_MICROBLAZE) += device_tree.o
+obj-$(TARGET_PPC) += device_tree.o
+endif
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
ifdef QEMU_PROGW
# The linker builds a windows executable. Make also a console executable.
-$(QEMU_PROGW): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
+$(QEMU_PROGW): $(obj-y)
$(call LINK,$^)
$(QEMU_PROG): $(QEMU_PROGW)
$(call quiet-command,$(OBJCOPY) --subsystem console $(QEMU_PROGW) $(QEMU_PROG)," GEN $(TARGET_DIR)$(QEMU_PROG)")
else
-$(QEMU_PROG): $(obj-y) $(obj-$(TARGET_BASE_ARCH)-y)
+$(QEMU_PROG): $(obj-y)
$(call LINK,$^)
endif
+++ /dev/null
-/*
- * Arm "Angel" semihosting syscalls
- *
- * Copyright (c) 2005, 2007 CodeSourcery.
- * Written by Paul Brook.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-
-#include "cpu.h"
-#ifdef CONFIG_USER_ONLY
-#include "qemu.h"
-
-#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
-#else
-#include "qemu-common.h"
-#include "gdbstub.h"
-#include "hw/arm-misc.h"
-#endif
-
-#define TARGET_SYS_OPEN 0x01
-#define TARGET_SYS_CLOSE 0x02
-#define TARGET_SYS_WRITEC 0x03
-#define TARGET_SYS_WRITE0 0x04
-#define TARGET_SYS_WRITE 0x05
-#define TARGET_SYS_READ 0x06
-#define TARGET_SYS_READC 0x07
-#define TARGET_SYS_ISTTY 0x09
-#define TARGET_SYS_SEEK 0x0a
-#define TARGET_SYS_FLEN 0x0c
-#define TARGET_SYS_TMPNAM 0x0d
-#define TARGET_SYS_REMOVE 0x0e
-#define TARGET_SYS_RENAME 0x0f
-#define TARGET_SYS_CLOCK 0x10
-#define TARGET_SYS_TIME 0x11
-#define TARGET_SYS_SYSTEM 0x12
-#define TARGET_SYS_ERRNO 0x13
-#define TARGET_SYS_GET_CMDLINE 0x15
-#define TARGET_SYS_HEAPINFO 0x16
-#define TARGET_SYS_EXIT 0x18
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-#define GDB_O_RDONLY 0x000
-#define GDB_O_WRONLY 0x001
-#define GDB_O_RDWR 0x002
-#define GDB_O_APPEND 0x008
-#define GDB_O_CREAT 0x200
-#define GDB_O_TRUNC 0x400
-#define GDB_O_BINARY 0
-
-static int gdb_open_modeflags[12] = {
- GDB_O_RDONLY,
- GDB_O_RDONLY | GDB_O_BINARY,
- GDB_O_RDWR,
- GDB_O_RDWR | GDB_O_BINARY,
- GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC,
- GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
- GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC,
- GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
- GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND,
- GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY,
- GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
- GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY
-};
-
-static int open_modeflags[12] = {
- O_RDONLY,
- O_RDONLY | O_BINARY,
- O_RDWR,
- O_RDWR | O_BINARY,
- O_WRONLY | O_CREAT | O_TRUNC,
- O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
- O_RDWR | O_CREAT | O_TRUNC,
- O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
- O_WRONLY | O_CREAT | O_APPEND,
- O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
- O_RDWR | O_CREAT | O_APPEND,
- O_RDWR | O_CREAT | O_APPEND | O_BINARY
-};
-
-#ifdef CONFIG_USER_ONLY
-static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code)
-{
- if (code == (uint32_t)-1)
- ts->swi_errno = errno;
- return code;
-}
-#else
-static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
-{
- return code;
-}
-
-#include "softmmu-semi.h"
-#endif
-
-static target_ulong arm_semi_syscall_len;
-
-#if !defined(CONFIG_USER_ONLY)
-static target_ulong syscall_err;
-#endif
-
-static void arm_semi_cb(CPUARMState *env, target_ulong ret, target_ulong err)
-{
-#ifdef CONFIG_USER_ONLY
- TaskState *ts = env->opaque;
-#endif
-
- if (ret == (target_ulong)-1) {
-#ifdef CONFIG_USER_ONLY
- ts->swi_errno = err;
-#else
- syscall_err = err;
-#endif
- env->regs[0] = ret;
- } else {
- /* Fixup syscalls that use nonstardard return conventions. */
- switch (env->regs[0]) {
- case TARGET_SYS_WRITE:
- case TARGET_SYS_READ:
- env->regs[0] = arm_semi_syscall_len - ret;
- break;
- case TARGET_SYS_SEEK:
- env->regs[0] = 0;
- break;
- default:
- env->regs[0] = ret;
- break;
- }
- }
-}
-
-static void arm_semi_flen_cb(CPUARMState *env, target_ulong ret, target_ulong err)
-{
- /* The size is always stored in big-endian order, extract
- the value. We assume the size always fit in 32 bits. */
- uint32_t size;
- cpu_memory_rw_debug(env, env->regs[13]-64+32, (uint8_t *)&size, 4, 0);
- env->regs[0] = be32_to_cpu(size);
-#ifdef CONFIG_USER_ONLY
- ((TaskState *)env->opaque)->swi_errno = err;
-#else
- syscall_err = err;
-#endif
-}
-
-#define ARG(n) \
-({ \
- target_ulong __arg; \
- /* FIXME - handle get_user() failure */ \
- get_user_ual(__arg, args + (n) * 4); \
- __arg; \
-})
-#define SET_ARG(n, val) put_user_ual(val, args + (n) * 4)
-uint32_t do_arm_semihosting(CPUARMState *env)
-{
- target_ulong args;
- char * s;
- int nr;
- uint32_t ret;
- uint32_t len;
-#ifdef CONFIG_USER_ONLY
- TaskState *ts = env->opaque;
-#else
- CPUARMState *ts = env;
-#endif
-
- nr = env->regs[0];
- args = env->regs[1];
- switch (nr) {
- case TARGET_SYS_OPEN:
- if (!(s = lock_user_string(ARG(0))))
- /* FIXME - should this error code be -TARGET_EFAULT ? */
- return (uint32_t)-1;
- if (ARG(1) >= 12)
- return (uint32_t)-1;
- if (strcmp(s, ":tt") == 0) {
- if (ARG(1) < 4)
- return STDIN_FILENO;
- else
- return STDOUT_FILENO;
- }
- if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0),
- (int)ARG(2)+1, gdb_open_modeflags[ARG(1)]);
- return env->regs[0];
- } else {
- ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
- }
- unlock_user(s, ARG(0), 0);
- return ret;
- case TARGET_SYS_CLOSE:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "close,%x", ARG(0));
- return env->regs[0];
- } else {
- return set_swi_errno(ts, close(ARG(0)));
- }
- case TARGET_SYS_WRITEC:
- {
- char c;
-
- if (get_user_u8(c, args))
- /* FIXME - should this error code be -TARGET_EFAULT ? */
- return (uint32_t)-1;
- /* Write to debug console. stderr is near enough. */
- if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "write,2,%x,1", args);
- return env->regs[0];
- } else {
- return write(STDERR_FILENO, &c, 1);
- }
- }
- case TARGET_SYS_WRITE0:
- if (!(s = lock_user_string(args)))
- /* FIXME - should this error code be -TARGET_EFAULT ? */
- return (uint32_t)-1;
- len = strlen(s);
- if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len);
- ret = env->regs[0];
- } else {
- ret = write(STDERR_FILENO, s, len);
- }
- unlock_user(s, args, 0);
- return ret;
- case TARGET_SYS_WRITE:
- len = ARG(2);
- if (use_gdb_syscalls()) {
- arm_semi_syscall_len = len;
- gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len);
- return env->regs[0];
- } else {
- if (!(s = lock_user(VERIFY_READ, ARG(1), len, 1)))
- /* FIXME - should this error code be -TARGET_EFAULT ? */
- return (uint32_t)-1;
- ret = set_swi_errno(ts, write(ARG(0), s, len));
- unlock_user(s, ARG(1), 0);
- if (ret == (uint32_t)-1)
- return -1;
- return len - ret;
- }
- case TARGET_SYS_READ:
- len = ARG(2);
- if (use_gdb_syscalls()) {
- arm_semi_syscall_len = len;
- gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len);
- return env->regs[0];
- } else {
- if (!(s = lock_user(VERIFY_WRITE, ARG(1), len, 0)))
- /* FIXME - should this error code be -TARGET_EFAULT ? */
- return (uint32_t)-1;
- do
- ret = set_swi_errno(ts, read(ARG(0), s, len));
- while (ret == -1 && errno == EINTR);
- unlock_user(s, ARG(1), len);
- if (ret == (uint32_t)-1)
- return -1;
- return len - ret;
- }
- case TARGET_SYS_READC:
- /* XXX: Read from debug cosole. Not implemented. */
- return 0;
- case TARGET_SYS_ISTTY:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "isatty,%x", ARG(0));
- return env->regs[0];
- } else {
- return isatty(ARG(0));
- }
- case TARGET_SYS_SEEK:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "lseek,%x,%x,0", ARG(0), ARG(1));
- return env->regs[0];
- } else {
- ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET));
- if (ret == (uint32_t)-1)
- return -1;
- return 0;
- }
- case TARGET_SYS_FLEN:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_flen_cb, "fstat,%x,%x",
- ARG(0), env->regs[13]-64);
- return env->regs[0];
- } else {
- struct stat buf;
- ret = set_swi_errno(ts, fstat(ARG(0), &buf));
- if (ret == (uint32_t)-1)
- return -1;
- return buf.st_size;
- }
- case TARGET_SYS_TMPNAM:
- /* XXX: Not implemented. */
- return -1;
- case TARGET_SYS_REMOVE:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)+1);
- ret = env->regs[0];
- } else {
- if (!(s = lock_user_string(ARG(0))))
- /* FIXME - should this error code be -TARGET_EFAULT ? */
- return (uint32_t)-1;
- ret = set_swi_errno(ts, remove(s));
- unlock_user(s, ARG(0), 0);
- }
- return ret;
- case TARGET_SYS_RENAME:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "rename,%s,%s",
- ARG(0), (int)ARG(1)+1, ARG(2), (int)ARG(3)+1);
- return env->regs[0];
- } else {
- char *s2;
- s = lock_user_string(ARG(0));
- s2 = lock_user_string(ARG(2));
- if (!s || !s2)
- /* FIXME - should this error code be -TARGET_EFAULT ? */
- ret = (uint32_t)-1;
- else
- ret = set_swi_errno(ts, rename(s, s2));
- if (s2)
- unlock_user(s2, ARG(2), 0);
- if (s)
- unlock_user(s, ARG(0), 0);
- return ret;
- }
- case TARGET_SYS_CLOCK:
- return clock() / (CLOCKS_PER_SEC / 100);
- case TARGET_SYS_TIME:
- return set_swi_errno(ts, time(NULL));
- case TARGET_SYS_SYSTEM:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)+1);
- return env->regs[0];
- } else {
- if (!(s = lock_user_string(ARG(0))))
- /* FIXME - should this error code be -TARGET_EFAULT ? */
- return (uint32_t)-1;
- ret = set_swi_errno(ts, system(s));
- unlock_user(s, ARG(0), 0);
- return ret;
- }
- case TARGET_SYS_ERRNO:
-#ifdef CONFIG_USER_ONLY
- return ts->swi_errno;
-#else
- return syscall_err;
-#endif
- case TARGET_SYS_GET_CMDLINE:
- {
- /* Build a command-line from the original argv.
- *
- * The inputs are:
- * * ARG(0), pointer to a buffer of at least the size
- * specified in ARG(1).
- * * ARG(1), size of the buffer pointed to by ARG(0) in
- * bytes.
- *
- * The outputs are:
- * * ARG(0), pointer to null-terminated string of the
- * command line.
- * * ARG(1), length of the string pointed to by ARG(0).
- */
-
- char *output_buffer;
- size_t input_size = ARG(1);
- size_t output_size;
- int status = 0;
-
- /* Compute the size of the output string. */
-#if !defined(CONFIG_USER_ONLY)
- output_size = strlen(ts->boot_info->kernel_filename)
- + 1 /* Separating space. */
- + strlen(ts->boot_info->kernel_cmdline)
- + 1; /* Terminating null byte. */
-#else
- unsigned int i;
-
- output_size = ts->info->arg_end - ts->info->arg_start;
- if (!output_size) {
- /* We special-case the "empty command line" case (argc==0).
- Just provide the terminating 0. */
- output_size = 1;
- }
-#endif
-
- if (output_size > input_size) {
- /* Not enough space to store command-line arguments. */
- return -1;
- }
-
- /* Adjust the command-line length. */
- SET_ARG(1, output_size - 1);
-
- /* Lock the buffer on the ARM side. */
- output_buffer = lock_user(VERIFY_WRITE, ARG(0), output_size, 0);
- if (!output_buffer) {
- return -1;
- }
-
- /* Copy the command-line arguments. */
-#if !defined(CONFIG_USER_ONLY)
- pstrcpy(output_buffer, output_size, ts->boot_info->kernel_filename);
- pstrcat(output_buffer, output_size, " ");
- pstrcat(output_buffer, output_size, ts->boot_info->kernel_cmdline);
-#else
- if (output_size == 1) {
- /* Empty command-line. */
- output_buffer[0] = '\0';
- goto out;
- }
-
- if (copy_from_user(output_buffer, ts->info->arg_start,
- output_size)) {
- status = -1;
- goto out;
- }
-
- /* Separate arguments by white spaces. */
- for (i = 0; i < output_size - 1; i++) {
- if (output_buffer[i] == 0) {
- output_buffer[i] = ' ';
- }
- }
- out:
-#endif
- /* Unlock the buffer on the ARM side. */
- unlock_user(output_buffer, ARG(0), output_size);
-
- return status;
- }
- case TARGET_SYS_HEAPINFO:
- {
- uint32_t *ptr;
- uint32_t limit;
-
-#ifdef CONFIG_USER_ONLY
- /* Some C libraries assume the heap immediately follows .bss, so
- allocate it using sbrk. */
- if (!ts->heap_limit) {
- abi_ulong ret;
-
- ts->heap_base = do_brk(0);
- limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
- /* Try a big heap, and reduce the size if that fails. */
- for (;;) {
- ret = do_brk(limit);
- if (ret >= limit) {
- break;
- }
- limit = (ts->heap_base >> 1) + (limit >> 1);
- }
- ts->heap_limit = limit;
- }
-
- if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0)))
- /* FIXME - should this error code be -TARGET_EFAULT ? */
- return (uint32_t)-1;
- ptr[0] = tswap32(ts->heap_base);
- ptr[1] = tswap32(ts->heap_limit);
- ptr[2] = tswap32(ts->stack_base);
- ptr[3] = tswap32(0); /* Stack limit. */
- unlock_user(ptr, ARG(0), 16);
-#else
- limit = ram_size;
- if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0)))
- /* FIXME - should this error code be -TARGET_EFAULT ? */
- return (uint32_t)-1;
- /* TODO: Make this use the limit of the loaded application. */
- ptr[0] = tswap32(limit / 2);
- ptr[1] = tswap32(limit);
- ptr[2] = tswap32(limit); /* Stack base */
- ptr[3] = tswap32(0); /* Stack limit. */
- unlock_user(ptr, ARG(0), 16);
-#endif
- return 0;
- }
- case TARGET_SYS_EXIT:
- gdb_exit(env, 0);
- exit(0);
- default:
- fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
- cpu_dump_state(env, stderr, fprintf, 0);
- abort();
- }
-}
esac
mkdir -p $target_dir
-mkdir -p $target_dir/fpu
-mkdir -p $target_dir/tcg
-mkdir -p $target_dir/ide
-mkdir -p $target_dir/usb
-mkdir -p $target_dir/9pfs
-mkdir -p $target_dir/kvm
-if test "$target_linux_user" = yes; then
- mkdir -p $target_dir/linux-user
-fi
-if test "$target_bsd_user" = yes; then
- mkdir -p $target_dir/bsd-user
-fi
-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/linux-user/arm/nwfpe
-fi
-symlink "$source_path/Makefile.target" "$target_dir/Makefile"
-
-
echo "# Automatically generated by configure - do not modify" > $config_target_mak
bflt="no"
exit 1
;;
esac
+# TARGET_BASE_ARCH needs to be defined after TARGET_ARCH
+if [ "$TARGET_BASE_ARCH" = "" ]; then
+ TARGET_BASE_ARCH=$TARGET_ARCH
+fi
+
+mkdir -p $target_dir/fpu
+mkdir -p $target_dir/tcg
+mkdir -p $target_dir/9pfs
+mkdir -p $target_dir/hw
+mkdir -p $target_dir/hw/ide
+mkdir -p $target_dir/hw/usb
+mkdir -p $target_dir/hw/kvm
+mkdir -p $target_dir/hw/$TARGET_ARCH
+mkdir -p $target_dir/hw/$TARGET_BASE_ARCH
+mkdir -p $target_dir/target-$TARGET_BASE_ARCH
+if test "$target_linux_user" = yes; then
+ mkdir -p $target_dir/linux-user
+fi
+if test "$target_bsd_user" = yes; then
+ mkdir -p $target_dir/bsd-user
+fi
+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/linux-user/arm/nwfpe
+fi
+symlink "$source_path/Makefile.target" "$target_dir/Makefile"
+
case "$target_arch2" in
alpha | sparc*)
target_arch_name="`echo $TARGET_ARCH | LC_ALL=C tr '[a-z]' '[A-Z]'`"
echo "TARGET_$target_arch_name=y" >> $config_target_mak
echo "TARGET_ARCH2=$target_arch2" >> $config_target_mak
-# TARGET_BASE_ARCH needs to be defined after TARGET_ARCH
-if [ "$TARGET_BASE_ARCH" = "" ]; then
- TARGET_BASE_ARCH=$TARGET_ARCH
-fi
echo "TARGET_BASE_ARCH=$TARGET_BASE_ARCH" >> $config_target_mak
if [ "$TARGET_ABI_DIR" = "" ]; then
TARGET_ABI_DIR=$TARGET_ARCH
--- /dev/null
+obj-y = mc146818rtc.o
+obj-y += alpha_pci.o alpha_dp264.o alpha_typhoon.o
+
+obj-y := $(addprefix ../,$(obj-y))
--- /dev/null
+obj-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
+obj-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
+obj-y += versatile_pci.o
+obj-y += versatile_i2c.o
+obj-y += cadence_uart.o
+obj-y += cadence_ttc.o
+obj-y += cadence_gem.o
+obj-y += xilinx_zynq.o zynq_slcr.o
+obj-y += arm_gic.o
+obj-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
+obj-y += exynos4210_gic.o exynos4210_combiner.o exynos4210.o
+obj-y += exynos4_boards.o exynos4210_uart.o exynos4210_pwm.o
+obj-y += exynos4210_pmu.o exynos4210_mct.o exynos4210_fimd.o
+obj-y += arm_l2x0.o
+obj-y += arm_mptimer.o a15mpcore.o
+obj-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
+obj-y += highbank.o
+obj-y += pl061.o
+obj-y += xgmac.o
+obj-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
+obj-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
+obj-y += gumstix.o
+obj-y += zaurus.o ide/microdrive.o spitz.o tosa.o tc6393xb.o
+obj-y += omap1.o omap_lcdc.o omap_dma.o omap_clk.o omap_mmc.o omap_i2c.o \
+ omap_gpio.o omap_intc.o omap_uart.o
+obj-y += omap2.o omap_dss.o soc_dma.o omap_gptimer.o omap_synctimer.o \
+ omap_gpmc.o omap_sdrc.o omap_spi.o omap_tap.o omap_l4.o
+obj-y += omap_sx1.o palm.o tsc210x.o
+obj-y += nseries.o blizzard.o onenand.o cbus.o tusb6010.o usb/hcd-musb.o
+obj-y += mst_fpga.o mainstone.o
+obj-y += z2.o
+obj-y += musicpal.o bitbang_i2c.o marvell_88w8618_audio.o
+obj-y += framebuffer.o
+obj-y += vexpress.o
+obj-y += strongarm.o
+obj-y += collie.o
+obj-y += pl041.o lm4549.o
+
+obj-y := $(addprefix ../,$(obj-y))
--- /dev/null
+# Boards
+obj-y = cris_pic_cpu.o
+obj-y += cris-boot.o
+obj-y += axis_dev88.o
+
+# IO blocks
+obj-y += etraxfs_dma.o
+obj-y += etraxfs_pic.o
+obj-y += etraxfs_eth.o
+obj-y += etraxfs_timer.o
+obj-y += etraxfs_ser.o
+
+obj-y := $(addprefix ../,$(obj-y))
--- /dev/null
+obj-y += mc146818rtc.o pc.o
+obj-y += apic_common.o apic.o kvmvapic.o
+obj-y += sga.o ioapic_common.o ioapic.o piix_pci.o
+obj-y += vmport.o
+obj-y += pci-hotplug.o smbios.o wdt_ib700.o
+obj-y += debugcon.o multiboot.o
+obj-y += pc_piix.o
+obj-y += pc_sysfw.o
+obj-$(CONFIG_XEN) += xen_platform.o xen_apic.o
+obj-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o kvm/i8259.o kvm/ioapic.o kvm/i8254.o
+obj-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
+
+obj-y := $(addprefix ../,$(obj-y))
--- /dev/null
+# LM32 boards
+obj-y += lm32_boards.o
+obj-y += milkymist.o
+
+# LM32 peripherals
+obj-y += lm32_pic.o
+obj-y += lm32_juart.o
+obj-y += lm32_timer.o
+obj-y += lm32_uart.o
+obj-y += lm32_sys.o
+obj-y += milkymist-ac97.o
+obj-y += milkymist-hpdmc.o
+obj-y += milkymist-memcard.o
+obj-y += milkymist-minimac2.o
+obj-y += milkymist-pfpu.o
+obj-y += milkymist-softusb.o
+obj-y += milkymist-sysctl.o
+obj-$(CONFIG_OPENGL) += milkymist-tmu2.o
+obj-y += milkymist-uart.o
+obj-y += milkymist-vgafb.o
+obj-y += framebuffer.o
+
+obj-y := $(addprefix ../,$(obj-y))
--- /dev/null
+obj-y = an5206.o mcf5206.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o
+obj-y += dummy_m68k.o
+
+obj-y := $(addprefix ../,$(obj-y))
--- /dev/null
+obj-y = petalogix_s3adsp1800_mmu.o
+obj-y += petalogix_ml605_mmu.o
+obj-y += microblaze_boot.o
+
+obj-y += microblaze_pic_cpu.o
+obj-y += xilinx_intc.o
+obj-y += xilinx_timer.o
+obj-y += xilinx_uartlite.o
+obj-y += xilinx_ethlite.o
+obj-y += xilinx_axidma.o
+obj-y += xilinx_axienet.o
+
+obj-y := $(addprefix ../,$(obj-y))
--- /dev/null
+obj-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
+obj-y += mips_addr.o mips_timer.o mips_int.o
+obj-y += gt64xxx.o mc146818rtc.o
+obj-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
+
+obj-y := $(addprefix ../,$(obj-y))
--- /dev/null
+# shared objects
+obj-y = ppc.o ppc_booke.o
+# PREP target
+obj-y += mc146818rtc.o
+obj-y += ppc_prep.o
+# OldWorld PowerMac
+obj-y += ppc_oldworld.o
+# NewWorld PowerMac
+obj-y += ppc_newworld.o
+# IBM pSeries (sPAPR)
+obj-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
+obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
+obj-$(CONFIG_PSERIES) += spapr_pci.o pci-hotplug.o
+# PowerPC 4xx boards
+obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
+obj-y += ppc440_bamboo.o
+# PowerPC E500 boards
+obj-y += ppce500_mpc8544ds.o mpc8544_guts.o ppce500_spin.o
+# PowerPC 440 Xilinx ML507 reference board.
+obj-y += virtex_ml507.o
+obj-$(CONFIG_KVM) += kvm_ppc.o
+# PowerPC OpenPIC
+obj-y += openpic.o
+
+# Xilinx PPC peripherals
+obj-y += xilinx_intc.o
+obj-y += xilinx_timer.o
+obj-y += xilinx_uartlite.o
+obj-y += xilinx_ethlite.o
+
+obj-y := $(addprefix ../,$(obj-y))
--- /dev/null
+obj-y = s390-virtio-bus.o s390-virtio.o
+
+obj-y := $(addprefix ../,$(obj-y))
--- /dev/null
+obj-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
+obj-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
+obj-y += ide/mmio.o
+
+obj-y := $(addprefix ../,$(obj-y))
--- /dev/null
+obj-y = sun4m.o lance.o tcx.o sun4m_iommu.o slavio_intctl.o
+obj-y += slavio_timer.o slavio_misc.o sparc32_dma.o
+obj-y += cs4231.o eccmemctl.o sbi.o sun4c_intctl.o leon3.o
+
+# GRLIB
+obj-y += grlib_gptimer.o grlib_irqmp.o grlib_apbuart.o
+
+obj-y := $(addprefix ../,$(obj-y))
--- /dev/null
+obj-y = sun4u.o apb_pci.o
+obj-y += mc146818rtc.o
+
+obj-y := $(addprefix ../,$(obj-y))
--- /dev/null
+obj-y += xtensa_pic.o
+obj-y += xtensa_sim.o
+obj-y += xtensa_lx60.o
+
+obj-y := $(addprefix ../,$(obj-y))
+++ /dev/null
-/*
- * qemu user ioport functions
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-
-#include "qemu.h"
-#include "qemu-common.h"
-#include "ioport.h"
-
-void cpu_outb(pio_addr_t addr, uint8_t val)
-{
- fprintf(stderr, "outb: port=0x%04"FMT_pioaddr", data=%02"PRIx8"\n",
- addr, val);
-}
-
-void cpu_outw(pio_addr_t addr, uint16_t val)
-{
- fprintf(stderr, "outw: port=0x%04"FMT_pioaddr", data=%04"PRIx16"\n",
- addr, val);
-}
-
-void cpu_outl(pio_addr_t addr, uint32_t val)
-{
- fprintf(stderr, "outl: port=0x%04"FMT_pioaddr", data=%08"PRIx32"\n",
- addr, val);
-}
-
-uint8_t cpu_inb(pio_addr_t addr)
-{
- fprintf(stderr, "inb: port=0x%04"FMT_pioaddr"\n", addr);
- return 0;
-}
-
-uint16_t cpu_inw(pio_addr_t addr)
-{
- fprintf(stderr, "inw: port=0x%04"FMT_pioaddr"\n", addr);
- return 0;
-}
-
-uint32_t cpu_inl(pio_addr_t addr)
-{
- fprintf(stderr, "inl: port=0x%04"FMT_pioaddr"\n", addr);
- return 0;
-}
+++ /dev/null
-/*
- * m68k/ColdFire Semihosting syscall interface
- *
- * Copyright (c) 2005-2007 CodeSourcery.
- *
- * 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/>.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/time.h>
-#include <time.h>
-
-#include "cpu.h"
-#if defined(CONFIG_USER_ONLY)
-#include "qemu.h"
-#define SEMIHOSTING_HEAP_SIZE (128 * 1024 * 1024)
-#else
-#include "qemu-common.h"
-#include "gdbstub.h"
-#include "softmmu-semi.h"
-#endif
-#include "sysemu.h"
-
-#define HOSTED_EXIT 0
-#define HOSTED_INIT_SIM 1
-#define HOSTED_OPEN 2
-#define HOSTED_CLOSE 3
-#define HOSTED_READ 4
-#define HOSTED_WRITE 5
-#define HOSTED_LSEEK 6
-#define HOSTED_RENAME 7
-#define HOSTED_UNLINK 8
-#define HOSTED_STAT 9
-#define HOSTED_FSTAT 10
-#define HOSTED_GETTIMEOFDAY 11
-#define HOSTED_ISATTY 12
-#define HOSTED_SYSTEM 13
-
-typedef uint32_t gdb_mode_t;
-typedef uint32_t gdb_time_t;
-
-struct m68k_gdb_stat {
- uint32_t gdb_st_dev; /* device */
- uint32_t gdb_st_ino; /* inode */
- gdb_mode_t gdb_st_mode; /* protection */
- uint32_t gdb_st_nlink; /* number of hard links */
- uint32_t gdb_st_uid; /* user ID of owner */
- uint32_t gdb_st_gid; /* group ID of owner */
- uint32_t gdb_st_rdev; /* device type (if inode device) */
- uint64_t gdb_st_size; /* total size, in bytes */
- uint64_t gdb_st_blksize; /* blocksize for filesystem I/O */
- uint64_t gdb_st_blocks; /* number of blocks allocated */
- gdb_time_t gdb_st_atime; /* time of last access */
- gdb_time_t gdb_st_mtime; /* time of last modification */
- gdb_time_t gdb_st_ctime; /* time of last change */
-} QEMU_PACKED;
-
-struct gdb_timeval {
- gdb_time_t tv_sec; /* second */
- uint64_t tv_usec; /* microsecond */
-} QEMU_PACKED;
-
-#define GDB_O_RDONLY 0x0
-#define GDB_O_WRONLY 0x1
-#define GDB_O_RDWR 0x2
-#define GDB_O_APPEND 0x8
-#define GDB_O_CREAT 0x200
-#define GDB_O_TRUNC 0x400
-#define GDB_O_EXCL 0x800
-
-static int translate_openflags(int flags)
-{
- int hf;
-
- if (flags & GDB_O_WRONLY)
- hf = O_WRONLY;
- else if (flags & GDB_O_RDWR)
- hf = O_RDWR;
- else
- hf = O_RDONLY;
-
- if (flags & GDB_O_APPEND) hf |= O_APPEND;
- if (flags & GDB_O_CREAT) hf |= O_CREAT;
- if (flags & GDB_O_TRUNC) hf |= O_TRUNC;
- if (flags & GDB_O_EXCL) hf |= O_EXCL;
-
- return hf;
-}
-
-static void translate_stat(CPUM68KState *env, target_ulong addr, struct stat *s)
-{
- struct m68k_gdb_stat *p;
-
- if (!(p = lock_user(VERIFY_WRITE, addr, sizeof(struct m68k_gdb_stat), 0)))
- /* FIXME - should this return an error code? */
- return;
- p->gdb_st_dev = cpu_to_be32(s->st_dev);
- p->gdb_st_ino = cpu_to_be32(s->st_ino);
- p->gdb_st_mode = cpu_to_be32(s->st_mode);
- p->gdb_st_nlink = cpu_to_be32(s->st_nlink);
- p->gdb_st_uid = cpu_to_be32(s->st_uid);
- p->gdb_st_gid = cpu_to_be32(s->st_gid);
- p->gdb_st_rdev = cpu_to_be32(s->st_rdev);
- p->gdb_st_size = cpu_to_be64(s->st_size);
-#ifdef _WIN32
- /* Windows stat is missing some fields. */
- p->gdb_st_blksize = 0;
- p->gdb_st_blocks = 0;
-#else
- p->gdb_st_blksize = cpu_to_be64(s->st_blksize);
- p->gdb_st_blocks = cpu_to_be64(s->st_blocks);
-#endif
- p->gdb_st_atime = cpu_to_be32(s->st_atime);
- p->gdb_st_mtime = cpu_to_be32(s->st_mtime);
- p->gdb_st_ctime = cpu_to_be32(s->st_ctime);
- unlock_user(p, addr, sizeof(struct m68k_gdb_stat));
-}
-
-static int m68k_semi_is_fseek;
-
-static void m68k_semi_cb(CPUM68KState *env, target_ulong ret, target_ulong err)
-{
- target_ulong args;
-
- args = env->dregs[1];
- if (m68k_semi_is_fseek) {
- /* FIXME: We've already lost the high bits of the fseek
- return value. */
- /* FIXME - handle put_user() failure */
- put_user_u32(0, args);
- args += 4;
- m68k_semi_is_fseek = 0;
- }
- /* FIXME - handle put_user() failure */
- put_user_u32(ret, args);
- put_user_u32(errno, args + 4);
-}
-
-#define ARG(n) \
-({ \
- target_ulong __arg; \
- /* FIXME - handle get_user() failure */ \
- get_user_ual(__arg, args + (n) * 4); \
- __arg; \
-})
-#define PARG(x) ((unsigned long)ARG(x))
-void do_m68k_semihosting(CPUM68KState *env, int nr)
-{
- uint32_t args;
- void *p;
- void *q;
- uint32_t len;
- uint32_t result;
-
- args = env->dregs[1];
- switch (nr) {
- case HOSTED_EXIT:
- gdb_exit(env, env->dregs[0]);
- exit(env->dregs[0]);
- case HOSTED_OPEN:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(m68k_semi_cb, "open,%s,%x,%x", ARG(0), (int)ARG(1),
- ARG(2), ARG(3));
- return;
- } else {
- if (!(p = lock_user_string(ARG(0)))) {
- /* FIXME - check error code? */
- result = -1;
- } else {
- result = open(p, translate_openflags(ARG(2)), ARG(3));
- unlock_user(p, ARG(0), 0);
- }
- }
- break;
- case HOSTED_CLOSE:
- {
- /* Ignore attempts to close stdin/out/err. */
- int fd = ARG(0);
- if (fd > 2) {
- if (use_gdb_syscalls()) {
- gdb_do_syscall(m68k_semi_cb, "close,%x", ARG(0));
- return;
- } else {
- result = close(fd);
- }
- } else {
- result = 0;
- }
- break;
- }
- case HOSTED_READ:
- len = ARG(2);
- if (use_gdb_syscalls()) {
- gdb_do_syscall(m68k_semi_cb, "read,%x,%x,%x",
- ARG(0), ARG(1), len);
- return;
- } else {
- if (!(p = lock_user(VERIFY_WRITE, ARG(1), len, 0))) {
- /* FIXME - check error code? */
- result = -1;
- } else {
- result = read(ARG(0), p, len);
- unlock_user(p, ARG(1), len);
- }
- }
- break;
- case HOSTED_WRITE:
- len = ARG(2);
- if (use_gdb_syscalls()) {
- gdb_do_syscall(m68k_semi_cb, "write,%x,%x,%x",
- ARG(0), ARG(1), len);
- return;
- } else {
- if (!(p = lock_user(VERIFY_READ, ARG(1), len, 1))) {
- /* FIXME - check error code? */
- result = -1;
- } else {
- result = write(ARG(0), p, len);
- unlock_user(p, ARG(0), 0);
- }
- }
- break;
- case HOSTED_LSEEK:
- {
- uint64_t off;
- off = (uint32_t)ARG(2) | ((uint64_t)ARG(1) << 32);
- if (use_gdb_syscalls()) {
- m68k_semi_is_fseek = 1;
- gdb_do_syscall(m68k_semi_cb, "fseek,%x,%lx,%x",
- ARG(0), off, ARG(3));
- } else {
- off = lseek(ARG(0), off, ARG(3));
- /* FIXME - handle put_user() failure */
- put_user_u32(off >> 32, args);
- put_user_u32(off, args + 4);
- put_user_u32(errno, args + 8);
- }
- return;
- }
- case HOSTED_RENAME:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(m68k_semi_cb, "rename,%s,%s",
- ARG(0), (int)ARG(1), ARG(2), (int)ARG(3));
- return;
- } else {
- p = lock_user_string(ARG(0));
- q = lock_user_string(ARG(2));
- if (!p || !q) {
- /* FIXME - check error code? */
- result = -1;
- } else {
- result = rename(p, q);
- }
- unlock_user(p, ARG(0), 0);
- unlock_user(q, ARG(2), 0);
- }
- break;
- case HOSTED_UNLINK:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(m68k_semi_cb, "unlink,%s",
- ARG(0), (int)ARG(1));
- return;
- } else {
- if (!(p = lock_user_string(ARG(0)))) {
- /* FIXME - check error code? */
- result = -1;
- } else {
- result = unlink(p);
- unlock_user(p, ARG(0), 0);
- }
- }
- break;
- case HOSTED_STAT:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(m68k_semi_cb, "stat,%s,%x",
- ARG(0), (int)ARG(1), ARG(2));
- return;
- } else {
- struct stat s;
- if (!(p = lock_user_string(ARG(0)))) {
- /* FIXME - check error code? */
- result = -1;
- } else {
- result = stat(p, &s);
- unlock_user(p, ARG(0), 0);
- }
- if (result == 0) {
- translate_stat(env, ARG(2), &s);
- }
- }
- break;
- case HOSTED_FSTAT:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(m68k_semi_cb, "fstat,%x,%x",
- ARG(0), ARG(1));
- return;
- } else {
- struct stat s;
- result = fstat(ARG(0), &s);
- if (result == 0) {
- translate_stat(env, ARG(1), &s);
- }
- }
- break;
- case HOSTED_GETTIMEOFDAY:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(m68k_semi_cb, "gettimeofday,%x,%x",
- ARG(0), ARG(1));
- return;
- } else {
- qemu_timeval tv;
- struct gdb_timeval *p;
- result = qemu_gettimeofday(&tv);
- if (result != 0) {
- if (!(p = lock_user(VERIFY_WRITE,
- ARG(0), sizeof(struct gdb_timeval), 0))) {
- /* FIXME - check error code? */
- result = -1;
- } else {
- p->tv_sec = cpu_to_be32(tv.tv_sec);
- p->tv_usec = cpu_to_be64(tv.tv_usec);
- unlock_user(p, ARG(0), sizeof(struct gdb_timeval));
- }
- }
- }
- break;
- case HOSTED_ISATTY:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(m68k_semi_cb, "isatty,%x", ARG(0));
- return;
- } else {
- result = isatty(ARG(0));
- }
- break;
- case HOSTED_SYSTEM:
- if (use_gdb_syscalls()) {
- gdb_do_syscall(m68k_semi_cb, "system,%s",
- ARG(0), (int)ARG(1));
- return;
- } else {
- if (!(p = lock_user_string(ARG(0)))) {
- /* FIXME - check error code? */
- result = -1;
- } else {
- result = system(p);
- unlock_user(p, ARG(0), 0);
- }
- }
- break;
- case HOSTED_INIT_SIM:
-#if defined(CONFIG_USER_ONLY)
- {
- TaskState *ts = env->opaque;
- /* Allocate the heap using sbrk. */
- if (!ts->heap_limit) {
- abi_ulong ret;
- uint32_t size;
- uint32_t base;
-
- base = do_brk(0);
- size = SEMIHOSTING_HEAP_SIZE;
- /* Try a big heap, and reduce the size if that fails. */
- for (;;) {
- ret = do_brk(base + size);
- if (ret >= (base + size)) {
- break;
- }
- size >>= 1;
- }
- ts->heap_limit = base + size;
- }
- /* This call may happen before we have writable memory, so return
- values directly in registers. */
- env->dregs[1] = ts->heap_limit;
- env->aregs[7] = ts->stack_base;
- }
-#else
- /* FIXME: This is wrong for boards where RAM does not start at
- address zero. */
- env->dregs[1] = ram_size;
- env->aregs[7] = ram_size;
-#endif
- return;
- default:
- cpu_abort(env, "Unsupported semihosting syscall %d\n", nr);
- result = 0;
- }
- /* FIXME - handle put_user() failure */
- put_user_u32(result, args);
- put_user_u32(errno, args + 4);
-}
--- /dev/null
+# still empty
--- /dev/null
+obj-y += arm-semi.o
--- /dev/null
+/*
+ * Arm "Angel" semihosting syscalls
+ *
+ * Copyright (c) 2005, 2007 CodeSourcery.
+ * Written by Paul Brook.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+#include "cpu.h"
+#ifdef CONFIG_USER_ONLY
+#include "qemu.h"
+
+#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
+#else
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "hw/arm-misc.h"
+#endif
+
+#define TARGET_SYS_OPEN 0x01
+#define TARGET_SYS_CLOSE 0x02
+#define TARGET_SYS_WRITEC 0x03
+#define TARGET_SYS_WRITE0 0x04
+#define TARGET_SYS_WRITE 0x05
+#define TARGET_SYS_READ 0x06
+#define TARGET_SYS_READC 0x07
+#define TARGET_SYS_ISTTY 0x09
+#define TARGET_SYS_SEEK 0x0a
+#define TARGET_SYS_FLEN 0x0c
+#define TARGET_SYS_TMPNAM 0x0d
+#define TARGET_SYS_REMOVE 0x0e
+#define TARGET_SYS_RENAME 0x0f
+#define TARGET_SYS_CLOCK 0x10
+#define TARGET_SYS_TIME 0x11
+#define TARGET_SYS_SYSTEM 0x12
+#define TARGET_SYS_ERRNO 0x13
+#define TARGET_SYS_GET_CMDLINE 0x15
+#define TARGET_SYS_HEAPINFO 0x16
+#define TARGET_SYS_EXIT 0x18
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#define GDB_O_RDONLY 0x000
+#define GDB_O_WRONLY 0x001
+#define GDB_O_RDWR 0x002
+#define GDB_O_APPEND 0x008
+#define GDB_O_CREAT 0x200
+#define GDB_O_TRUNC 0x400
+#define GDB_O_BINARY 0
+
+static int gdb_open_modeflags[12] = {
+ GDB_O_RDONLY,
+ GDB_O_RDONLY | GDB_O_BINARY,
+ GDB_O_RDWR,
+ GDB_O_RDWR | GDB_O_BINARY,
+ GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC,
+ GDB_O_WRONLY | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
+ GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC,
+ GDB_O_RDWR | GDB_O_CREAT | GDB_O_TRUNC | GDB_O_BINARY,
+ GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND,
+ GDB_O_WRONLY | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY,
+ GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
+ GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND | GDB_O_BINARY
+};
+
+static int open_modeflags[12] = {
+ O_RDONLY,
+ O_RDONLY | O_BINARY,
+ O_RDWR,
+ O_RDWR | O_BINARY,
+ O_WRONLY | O_CREAT | O_TRUNC,
+ O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
+ O_RDWR | O_CREAT | O_TRUNC,
+ O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
+ O_WRONLY | O_CREAT | O_APPEND,
+ O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
+ O_RDWR | O_CREAT | O_APPEND,
+ O_RDWR | O_CREAT | O_APPEND | O_BINARY
+};
+
+#ifdef CONFIG_USER_ONLY
+static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code)
+{
+ if (code == (uint32_t)-1)
+ ts->swi_errno = errno;
+ return code;
+}
+#else
+static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
+{
+ return code;
+}
+
+#include "softmmu-semi.h"
+#endif
+
+static target_ulong arm_semi_syscall_len;
+
+#if !defined(CONFIG_USER_ONLY)
+static target_ulong syscall_err;
+#endif
+
+static void arm_semi_cb(CPUARMState *env, target_ulong ret, target_ulong err)
+{
+#ifdef CONFIG_USER_ONLY
+ TaskState *ts = env->opaque;
+#endif
+
+ if (ret == (target_ulong)-1) {
+#ifdef CONFIG_USER_ONLY
+ ts->swi_errno = err;
+#else
+ syscall_err = err;
+#endif
+ env->regs[0] = ret;
+ } else {
+ /* Fixup syscalls that use nonstardard return conventions. */
+ switch (env->regs[0]) {
+ case TARGET_SYS_WRITE:
+ case TARGET_SYS_READ:
+ env->regs[0] = arm_semi_syscall_len - ret;
+ break;
+ case TARGET_SYS_SEEK:
+ env->regs[0] = 0;
+ break;
+ default:
+ env->regs[0] = ret;
+ break;
+ }
+ }
+}
+
+static void arm_semi_flen_cb(CPUARMState *env, target_ulong ret, target_ulong err)
+{
+ /* The size is always stored in big-endian order, extract
+ the value. We assume the size always fit in 32 bits. */
+ uint32_t size;
+ cpu_memory_rw_debug(env, env->regs[13]-64+32, (uint8_t *)&size, 4, 0);
+ env->regs[0] = be32_to_cpu(size);
+#ifdef CONFIG_USER_ONLY
+ ((TaskState *)env->opaque)->swi_errno = err;
+#else
+ syscall_err = err;
+#endif
+}
+
+#define ARG(n) \
+({ \
+ target_ulong __arg; \
+ /* FIXME - handle get_user() failure */ \
+ get_user_ual(__arg, args + (n) * 4); \
+ __arg; \
+})
+#define SET_ARG(n, val) put_user_ual(val, args + (n) * 4)
+uint32_t do_arm_semihosting(CPUARMState *env)
+{
+ target_ulong args;
+ char * s;
+ int nr;
+ uint32_t ret;
+ uint32_t len;
+#ifdef CONFIG_USER_ONLY
+ TaskState *ts = env->opaque;
+#else
+ CPUARMState *ts = env;
+#endif
+
+ nr = env->regs[0];
+ args = env->regs[1];
+ switch (nr) {
+ case TARGET_SYS_OPEN:
+ if (!(s = lock_user_string(ARG(0))))
+ /* FIXME - should this error code be -TARGET_EFAULT ? */
+ return (uint32_t)-1;
+ if (ARG(1) >= 12)
+ return (uint32_t)-1;
+ if (strcmp(s, ":tt") == 0) {
+ if (ARG(1) < 4)
+ return STDIN_FILENO;
+ else
+ return STDOUT_FILENO;
+ }
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(arm_semi_cb, "open,%s,%x,1a4", ARG(0),
+ (int)ARG(2)+1, gdb_open_modeflags[ARG(1)]);
+ return env->regs[0];
+ } else {
+ ret = set_swi_errno(ts, open(s, open_modeflags[ARG(1)], 0644));
+ }
+ unlock_user(s, ARG(0), 0);
+ return ret;
+ case TARGET_SYS_CLOSE:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(arm_semi_cb, "close,%x", ARG(0));
+ return env->regs[0];
+ } else {
+ return set_swi_errno(ts, close(ARG(0)));
+ }
+ case TARGET_SYS_WRITEC:
+ {
+ char c;
+
+ if (get_user_u8(c, args))
+ /* FIXME - should this error code be -TARGET_EFAULT ? */
+ return (uint32_t)-1;
+ /* Write to debug console. stderr is near enough. */
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(arm_semi_cb, "write,2,%x,1", args);
+ return env->regs[0];
+ } else {
+ return write(STDERR_FILENO, &c, 1);
+ }
+ }
+ case TARGET_SYS_WRITE0:
+ if (!(s = lock_user_string(args)))
+ /* FIXME - should this error code be -TARGET_EFAULT ? */
+ return (uint32_t)-1;
+ len = strlen(s);
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(arm_semi_cb, "write,2,%x,%x\n", args, len);
+ ret = env->regs[0];
+ } else {
+ ret = write(STDERR_FILENO, s, len);
+ }
+ unlock_user(s, args, 0);
+ return ret;
+ case TARGET_SYS_WRITE:
+ len = ARG(2);
+ if (use_gdb_syscalls()) {
+ arm_semi_syscall_len = len;
+ gdb_do_syscall(arm_semi_cb, "write,%x,%x,%x", ARG(0), ARG(1), len);
+ return env->regs[0];
+ } else {
+ if (!(s = lock_user(VERIFY_READ, ARG(1), len, 1)))
+ /* FIXME - should this error code be -TARGET_EFAULT ? */
+ return (uint32_t)-1;
+ ret = set_swi_errno(ts, write(ARG(0), s, len));
+ unlock_user(s, ARG(1), 0);
+ if (ret == (uint32_t)-1)
+ return -1;
+ return len - ret;
+ }
+ case TARGET_SYS_READ:
+ len = ARG(2);
+ if (use_gdb_syscalls()) {
+ arm_semi_syscall_len = len;
+ gdb_do_syscall(arm_semi_cb, "read,%x,%x,%x", ARG(0), ARG(1), len);
+ return env->regs[0];
+ } else {
+ if (!(s = lock_user(VERIFY_WRITE, ARG(1), len, 0)))
+ /* FIXME - should this error code be -TARGET_EFAULT ? */
+ return (uint32_t)-1;
+ do
+ ret = set_swi_errno(ts, read(ARG(0), s, len));
+ while (ret == -1 && errno == EINTR);
+ unlock_user(s, ARG(1), len);
+ if (ret == (uint32_t)-1)
+ return -1;
+ return len - ret;
+ }
+ case TARGET_SYS_READC:
+ /* XXX: Read from debug cosole. Not implemented. */
+ return 0;
+ case TARGET_SYS_ISTTY:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(arm_semi_cb, "isatty,%x", ARG(0));
+ return env->regs[0];
+ } else {
+ return isatty(ARG(0));
+ }
+ case TARGET_SYS_SEEK:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(arm_semi_cb, "lseek,%x,%x,0", ARG(0), ARG(1));
+ return env->regs[0];
+ } else {
+ ret = set_swi_errno(ts, lseek(ARG(0), ARG(1), SEEK_SET));
+ if (ret == (uint32_t)-1)
+ return -1;
+ return 0;
+ }
+ case TARGET_SYS_FLEN:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(arm_semi_flen_cb, "fstat,%x,%x",
+ ARG(0), env->regs[13]-64);
+ return env->regs[0];
+ } else {
+ struct stat buf;
+ ret = set_swi_errno(ts, fstat(ARG(0), &buf));
+ if (ret == (uint32_t)-1)
+ return -1;
+ return buf.st_size;
+ }
+ case TARGET_SYS_TMPNAM:
+ /* XXX: Not implemented. */
+ return -1;
+ case TARGET_SYS_REMOVE:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(arm_semi_cb, "unlink,%s", ARG(0), (int)ARG(1)+1);
+ ret = env->regs[0];
+ } else {
+ if (!(s = lock_user_string(ARG(0))))
+ /* FIXME - should this error code be -TARGET_EFAULT ? */
+ return (uint32_t)-1;
+ ret = set_swi_errno(ts, remove(s));
+ unlock_user(s, ARG(0), 0);
+ }
+ return ret;
+ case TARGET_SYS_RENAME:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(arm_semi_cb, "rename,%s,%s",
+ ARG(0), (int)ARG(1)+1, ARG(2), (int)ARG(3)+1);
+ return env->regs[0];
+ } else {
+ char *s2;
+ s = lock_user_string(ARG(0));
+ s2 = lock_user_string(ARG(2));
+ if (!s || !s2)
+ /* FIXME - should this error code be -TARGET_EFAULT ? */
+ ret = (uint32_t)-1;
+ else
+ ret = set_swi_errno(ts, rename(s, s2));
+ if (s2)
+ unlock_user(s2, ARG(2), 0);
+ if (s)
+ unlock_user(s, ARG(0), 0);
+ return ret;
+ }
+ case TARGET_SYS_CLOCK:
+ return clock() / (CLOCKS_PER_SEC / 100);
+ case TARGET_SYS_TIME:
+ return set_swi_errno(ts, time(NULL));
+ case TARGET_SYS_SYSTEM:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(arm_semi_cb, "system,%s", ARG(0), (int)ARG(1)+1);
+ return env->regs[0];
+ } else {
+ if (!(s = lock_user_string(ARG(0))))
+ /* FIXME - should this error code be -TARGET_EFAULT ? */
+ return (uint32_t)-1;
+ ret = set_swi_errno(ts, system(s));
+ unlock_user(s, ARG(0), 0);
+ return ret;
+ }
+ case TARGET_SYS_ERRNO:
+#ifdef CONFIG_USER_ONLY
+ return ts->swi_errno;
+#else
+ return syscall_err;
+#endif
+ case TARGET_SYS_GET_CMDLINE:
+ {
+ /* Build a command-line from the original argv.
+ *
+ * The inputs are:
+ * * ARG(0), pointer to a buffer of at least the size
+ * specified in ARG(1).
+ * * ARG(1), size of the buffer pointed to by ARG(0) in
+ * bytes.
+ *
+ * The outputs are:
+ * * ARG(0), pointer to null-terminated string of the
+ * command line.
+ * * ARG(1), length of the string pointed to by ARG(0).
+ */
+
+ char *output_buffer;
+ size_t input_size = ARG(1);
+ size_t output_size;
+ int status = 0;
+
+ /* Compute the size of the output string. */
+#if !defined(CONFIG_USER_ONLY)
+ output_size = strlen(ts->boot_info->kernel_filename)
+ + 1 /* Separating space. */
+ + strlen(ts->boot_info->kernel_cmdline)
+ + 1; /* Terminating null byte. */
+#else
+ unsigned int i;
+
+ output_size = ts->info->arg_end - ts->info->arg_start;
+ if (!output_size) {
+ /* We special-case the "empty command line" case (argc==0).
+ Just provide the terminating 0. */
+ output_size = 1;
+ }
+#endif
+
+ if (output_size > input_size) {
+ /* Not enough space to store command-line arguments. */
+ return -1;
+ }
+
+ /* Adjust the command-line length. */
+ SET_ARG(1, output_size - 1);
+
+ /* Lock the buffer on the ARM side. */
+ output_buffer = lock_user(VERIFY_WRITE, ARG(0), output_size, 0);
+ if (!output_buffer) {
+ return -1;
+ }
+
+ /* Copy the command-line arguments. */
+#if !defined(CONFIG_USER_ONLY)
+ pstrcpy(output_buffer, output_size, ts->boot_info->kernel_filename);
+ pstrcat(output_buffer, output_size, " ");
+ pstrcat(output_buffer, output_size, ts->boot_info->kernel_cmdline);
+#else
+ if (output_size == 1) {
+ /* Empty command-line. */
+ output_buffer[0] = '\0';
+ goto out;
+ }
+
+ if (copy_from_user(output_buffer, ts->info->arg_start,
+ output_size)) {
+ status = -1;
+ goto out;
+ }
+
+ /* Separate arguments by white spaces. */
+ for (i = 0; i < output_size - 1; i++) {
+ if (output_buffer[i] == 0) {
+ output_buffer[i] = ' ';
+ }
+ }
+ out:
+#endif
+ /* Unlock the buffer on the ARM side. */
+ unlock_user(output_buffer, ARG(0), output_size);
+
+ return status;
+ }
+ case TARGET_SYS_HEAPINFO:
+ {
+ uint32_t *ptr;
+ uint32_t limit;
+
+#ifdef CONFIG_USER_ONLY
+ /* Some C libraries assume the heap immediately follows .bss, so
+ allocate it using sbrk. */
+ if (!ts->heap_limit) {
+ abi_ulong ret;
+
+ ts->heap_base = do_brk(0);
+ limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
+ /* Try a big heap, and reduce the size if that fails. */
+ for (;;) {
+ ret = do_brk(limit);
+ if (ret >= limit) {
+ break;
+ }
+ limit = (ts->heap_base >> 1) + (limit >> 1);
+ }
+ ts->heap_limit = limit;
+ }
+
+ if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0)))
+ /* FIXME - should this error code be -TARGET_EFAULT ? */
+ return (uint32_t)-1;
+ ptr[0] = tswap32(ts->heap_base);
+ ptr[1] = tswap32(ts->heap_limit);
+ ptr[2] = tswap32(ts->stack_base);
+ ptr[3] = tswap32(0); /* Stack limit. */
+ unlock_user(ptr, ARG(0), 16);
+#else
+ limit = ram_size;
+ if (!(ptr = lock_user(VERIFY_WRITE, ARG(0), 16, 0)))
+ /* FIXME - should this error code be -TARGET_EFAULT ? */
+ return (uint32_t)-1;
+ /* TODO: Make this use the limit of the loaded application. */
+ ptr[0] = tswap32(limit / 2);
+ ptr[1] = tswap32(limit);
+ ptr[2] = tswap32(limit); /* Stack base */
+ ptr[3] = tswap32(0); /* Stack limit. */
+ unlock_user(ptr, ARG(0), 16);
+#endif
+ return 0;
+ }
+ case TARGET_SYS_EXIT:
+ gdb_exit(env, 0);
+ exit(0);
+ default:
+ fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
+ cpu_dump_state(env, stderr, fprintf, 0);
+ abort();
+ }
+}
--- /dev/null
+# still empty
--- /dev/null
+obj-$(CONFIG_KVM) += hyperv.o
+obj-$(CONFIG_LINUX_USER) += ioport-user.o
+obj-$(CONFIG_BSD_USER) += ioport-user.o
--- /dev/null
+/*
+ * qemu user ioport functions
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+
+#include "qemu.h"
+#include "qemu-common.h"
+#include "ioport.h"
+
+void cpu_outb(pio_addr_t addr, uint8_t val)
+{
+ fprintf(stderr, "outb: port=0x%04"FMT_pioaddr", data=%02"PRIx8"\n",
+ addr, val);
+}
+
+void cpu_outw(pio_addr_t addr, uint16_t val)
+{
+ fprintf(stderr, "outw: port=0x%04"FMT_pioaddr", data=%04"PRIx16"\n",
+ addr, val);
+}
+
+void cpu_outl(pio_addr_t addr, uint32_t val)
+{
+ fprintf(stderr, "outl: port=0x%04"FMT_pioaddr", data=%08"PRIx32"\n",
+ addr, val);
+}
+
+uint8_t cpu_inb(pio_addr_t addr)
+{
+ fprintf(stderr, "inb: port=0x%04"FMT_pioaddr"\n", addr);
+ return 0;
+}
+
+uint16_t cpu_inw(pio_addr_t addr)
+{
+ fprintf(stderr, "inw: port=0x%04"FMT_pioaddr"\n", addr);
+ return 0;
+}
+
+uint32_t cpu_inl(pio_addr_t addr)
+{
+ fprintf(stderr, "inl: port=0x%04"FMT_pioaddr"\n", addr);
+ return 0;
+}
--- /dev/null
+# still empty
--- /dev/null
+obj-y += m68k-semi.o
--- /dev/null
+/*
+ * m68k/ColdFire Semihosting syscall interface
+ *
+ * Copyright (c) 2005-2007 CodeSourcery.
+ *
+ * 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/>.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include "cpu.h"
+#if defined(CONFIG_USER_ONLY)
+#include "qemu.h"
+#define SEMIHOSTING_HEAP_SIZE (128 * 1024 * 1024)
+#else
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "softmmu-semi.h"
+#endif
+#include "sysemu.h"
+
+#define HOSTED_EXIT 0
+#define HOSTED_INIT_SIM 1
+#define HOSTED_OPEN 2
+#define HOSTED_CLOSE 3
+#define HOSTED_READ 4
+#define HOSTED_WRITE 5
+#define HOSTED_LSEEK 6
+#define HOSTED_RENAME 7
+#define HOSTED_UNLINK 8
+#define HOSTED_STAT 9
+#define HOSTED_FSTAT 10
+#define HOSTED_GETTIMEOFDAY 11
+#define HOSTED_ISATTY 12
+#define HOSTED_SYSTEM 13
+
+typedef uint32_t gdb_mode_t;
+typedef uint32_t gdb_time_t;
+
+struct m68k_gdb_stat {
+ uint32_t gdb_st_dev; /* device */
+ uint32_t gdb_st_ino; /* inode */
+ gdb_mode_t gdb_st_mode; /* protection */
+ uint32_t gdb_st_nlink; /* number of hard links */
+ uint32_t gdb_st_uid; /* user ID of owner */
+ uint32_t gdb_st_gid; /* group ID of owner */
+ uint32_t gdb_st_rdev; /* device type (if inode device) */
+ uint64_t gdb_st_size; /* total size, in bytes */
+ uint64_t gdb_st_blksize; /* blocksize for filesystem I/O */
+ uint64_t gdb_st_blocks; /* number of blocks allocated */
+ gdb_time_t gdb_st_atime; /* time of last access */
+ gdb_time_t gdb_st_mtime; /* time of last modification */
+ gdb_time_t gdb_st_ctime; /* time of last change */
+} QEMU_PACKED;
+
+struct gdb_timeval {
+ gdb_time_t tv_sec; /* second */
+ uint64_t tv_usec; /* microsecond */
+} QEMU_PACKED;
+
+#define GDB_O_RDONLY 0x0
+#define GDB_O_WRONLY 0x1
+#define GDB_O_RDWR 0x2
+#define GDB_O_APPEND 0x8
+#define GDB_O_CREAT 0x200
+#define GDB_O_TRUNC 0x400
+#define GDB_O_EXCL 0x800
+
+static int translate_openflags(int flags)
+{
+ int hf;
+
+ if (flags & GDB_O_WRONLY)
+ hf = O_WRONLY;
+ else if (flags & GDB_O_RDWR)
+ hf = O_RDWR;
+ else
+ hf = O_RDONLY;
+
+ if (flags & GDB_O_APPEND) hf |= O_APPEND;
+ if (flags & GDB_O_CREAT) hf |= O_CREAT;
+ if (flags & GDB_O_TRUNC) hf |= O_TRUNC;
+ if (flags & GDB_O_EXCL) hf |= O_EXCL;
+
+ return hf;
+}
+
+static void translate_stat(CPUM68KState *env, target_ulong addr, struct stat *s)
+{
+ struct m68k_gdb_stat *p;
+
+ if (!(p = lock_user(VERIFY_WRITE, addr, sizeof(struct m68k_gdb_stat), 0)))
+ /* FIXME - should this return an error code? */
+ return;
+ p->gdb_st_dev = cpu_to_be32(s->st_dev);
+ p->gdb_st_ino = cpu_to_be32(s->st_ino);
+ p->gdb_st_mode = cpu_to_be32(s->st_mode);
+ p->gdb_st_nlink = cpu_to_be32(s->st_nlink);
+ p->gdb_st_uid = cpu_to_be32(s->st_uid);
+ p->gdb_st_gid = cpu_to_be32(s->st_gid);
+ p->gdb_st_rdev = cpu_to_be32(s->st_rdev);
+ p->gdb_st_size = cpu_to_be64(s->st_size);
+#ifdef _WIN32
+ /* Windows stat is missing some fields. */
+ p->gdb_st_blksize = 0;
+ p->gdb_st_blocks = 0;
+#else
+ p->gdb_st_blksize = cpu_to_be64(s->st_blksize);
+ p->gdb_st_blocks = cpu_to_be64(s->st_blocks);
+#endif
+ p->gdb_st_atime = cpu_to_be32(s->st_atime);
+ p->gdb_st_mtime = cpu_to_be32(s->st_mtime);
+ p->gdb_st_ctime = cpu_to_be32(s->st_ctime);
+ unlock_user(p, addr, sizeof(struct m68k_gdb_stat));
+}
+
+static int m68k_semi_is_fseek;
+
+static void m68k_semi_cb(CPUM68KState *env, target_ulong ret, target_ulong err)
+{
+ target_ulong args;
+
+ args = env->dregs[1];
+ if (m68k_semi_is_fseek) {
+ /* FIXME: We've already lost the high bits of the fseek
+ return value. */
+ /* FIXME - handle put_user() failure */
+ put_user_u32(0, args);
+ args += 4;
+ m68k_semi_is_fseek = 0;
+ }
+ /* FIXME - handle put_user() failure */
+ put_user_u32(ret, args);
+ put_user_u32(errno, args + 4);
+}
+
+#define ARG(n) \
+({ \
+ target_ulong __arg; \
+ /* FIXME - handle get_user() failure */ \
+ get_user_ual(__arg, args + (n) * 4); \
+ __arg; \
+})
+#define PARG(x) ((unsigned long)ARG(x))
+void do_m68k_semihosting(CPUM68KState *env, int nr)
+{
+ uint32_t args;
+ void *p;
+ void *q;
+ uint32_t len;
+ uint32_t result;
+
+ args = env->dregs[1];
+ switch (nr) {
+ case HOSTED_EXIT:
+ gdb_exit(env, env->dregs[0]);
+ exit(env->dregs[0]);
+ case HOSTED_OPEN:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "open,%s,%x,%x", ARG(0), (int)ARG(1),
+ ARG(2), ARG(3));
+ return;
+ } else {
+ if (!(p = lock_user_string(ARG(0)))) {
+ /* FIXME - check error code? */
+ result = -1;
+ } else {
+ result = open(p, translate_openflags(ARG(2)), ARG(3));
+ unlock_user(p, ARG(0), 0);
+ }
+ }
+ break;
+ case HOSTED_CLOSE:
+ {
+ /* Ignore attempts to close stdin/out/err. */
+ int fd = ARG(0);
+ if (fd > 2) {
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "close,%x", ARG(0));
+ return;
+ } else {
+ result = close(fd);
+ }
+ } else {
+ result = 0;
+ }
+ break;
+ }
+ case HOSTED_READ:
+ len = ARG(2);
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "read,%x,%x,%x",
+ ARG(0), ARG(1), len);
+ return;
+ } else {
+ if (!(p = lock_user(VERIFY_WRITE, ARG(1), len, 0))) {
+ /* FIXME - check error code? */
+ result = -1;
+ } else {
+ result = read(ARG(0), p, len);
+ unlock_user(p, ARG(1), len);
+ }
+ }
+ break;
+ case HOSTED_WRITE:
+ len = ARG(2);
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "write,%x,%x,%x",
+ ARG(0), ARG(1), len);
+ return;
+ } else {
+ if (!(p = lock_user(VERIFY_READ, ARG(1), len, 1))) {
+ /* FIXME - check error code? */
+ result = -1;
+ } else {
+ result = write(ARG(0), p, len);
+ unlock_user(p, ARG(0), 0);
+ }
+ }
+ break;
+ case HOSTED_LSEEK:
+ {
+ uint64_t off;
+ off = (uint32_t)ARG(2) | ((uint64_t)ARG(1) << 32);
+ if (use_gdb_syscalls()) {
+ m68k_semi_is_fseek = 1;
+ gdb_do_syscall(m68k_semi_cb, "fseek,%x,%lx,%x",
+ ARG(0), off, ARG(3));
+ } else {
+ off = lseek(ARG(0), off, ARG(3));
+ /* FIXME - handle put_user() failure */
+ put_user_u32(off >> 32, args);
+ put_user_u32(off, args + 4);
+ put_user_u32(errno, args + 8);
+ }
+ return;
+ }
+ case HOSTED_RENAME:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "rename,%s,%s",
+ ARG(0), (int)ARG(1), ARG(2), (int)ARG(3));
+ return;
+ } else {
+ p = lock_user_string(ARG(0));
+ q = lock_user_string(ARG(2));
+ if (!p || !q) {
+ /* FIXME - check error code? */
+ result = -1;
+ } else {
+ result = rename(p, q);
+ }
+ unlock_user(p, ARG(0), 0);
+ unlock_user(q, ARG(2), 0);
+ }
+ break;
+ case HOSTED_UNLINK:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "unlink,%s",
+ ARG(0), (int)ARG(1));
+ return;
+ } else {
+ if (!(p = lock_user_string(ARG(0)))) {
+ /* FIXME - check error code? */
+ result = -1;
+ } else {
+ result = unlink(p);
+ unlock_user(p, ARG(0), 0);
+ }
+ }
+ break;
+ case HOSTED_STAT:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "stat,%s,%x",
+ ARG(0), (int)ARG(1), ARG(2));
+ return;
+ } else {
+ struct stat s;
+ if (!(p = lock_user_string(ARG(0)))) {
+ /* FIXME - check error code? */
+ result = -1;
+ } else {
+ result = stat(p, &s);
+ unlock_user(p, ARG(0), 0);
+ }
+ if (result == 0) {
+ translate_stat(env, ARG(2), &s);
+ }
+ }
+ break;
+ case HOSTED_FSTAT:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "fstat,%x,%x",
+ ARG(0), ARG(1));
+ return;
+ } else {
+ struct stat s;
+ result = fstat(ARG(0), &s);
+ if (result == 0) {
+ translate_stat(env, ARG(1), &s);
+ }
+ }
+ break;
+ case HOSTED_GETTIMEOFDAY:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "gettimeofday,%x,%x",
+ ARG(0), ARG(1));
+ return;
+ } else {
+ qemu_timeval tv;
+ struct gdb_timeval *p;
+ result = qemu_gettimeofday(&tv);
+ if (result != 0) {
+ if (!(p = lock_user(VERIFY_WRITE,
+ ARG(0), sizeof(struct gdb_timeval), 0))) {
+ /* FIXME - check error code? */
+ result = -1;
+ } else {
+ p->tv_sec = cpu_to_be32(tv.tv_sec);
+ p->tv_usec = cpu_to_be64(tv.tv_usec);
+ unlock_user(p, ARG(0), sizeof(struct gdb_timeval));
+ }
+ }
+ }
+ break;
+ case HOSTED_ISATTY:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "isatty,%x", ARG(0));
+ return;
+ } else {
+ result = isatty(ARG(0));
+ }
+ break;
+ case HOSTED_SYSTEM:
+ if (use_gdb_syscalls()) {
+ gdb_do_syscall(m68k_semi_cb, "system,%s",
+ ARG(0), (int)ARG(1));
+ return;
+ } else {
+ if (!(p = lock_user_string(ARG(0)))) {
+ /* FIXME - check error code? */
+ result = -1;
+ } else {
+ result = system(p);
+ unlock_user(p, ARG(0), 0);
+ }
+ }
+ break;
+ case HOSTED_INIT_SIM:
+#if defined(CONFIG_USER_ONLY)
+ {
+ TaskState *ts = env->opaque;
+ /* Allocate the heap using sbrk. */
+ if (!ts->heap_limit) {
+ abi_ulong ret;
+ uint32_t size;
+ uint32_t base;
+
+ base = do_brk(0);
+ size = SEMIHOSTING_HEAP_SIZE;
+ /* Try a big heap, and reduce the size if that fails. */
+ for (;;) {
+ ret = do_brk(base + size);
+ if (ret >= (base + size)) {
+ break;
+ }
+ size >>= 1;
+ }
+ ts->heap_limit = base + size;
+ }
+ /* This call may happen before we have writable memory, so return
+ values directly in registers. */
+ env->dregs[1] = ts->heap_limit;
+ env->aregs[7] = ts->stack_base;
+ }
+#else
+ /* FIXME: This is wrong for boards where RAM does not start at
+ address zero. */
+ env->dregs[1] = ram_size;
+ env->aregs[7] = ram_size;
+#endif
+ return;
+ default:
+ cpu_abort(env, "Unsupported semihosting syscall %d\n", nr);
+ result = 0;
+ }
+ /* FIXME - handle put_user() failure */
+ put_user_u32(result, args);
+ put_user_u32(errno, args + 4);
+}
--- /dev/null
+# still empty
--- /dev/null
+# still empty
--- /dev/null
+# still empty
--- /dev/null
+# still empty
--- /dev/null
+# still empty
--- /dev/null
+# still empty
--- /dev/null
+# still empty
--- /dev/null
+obj-y += xtensa-semi.o
+obj-y += core-dc232b.o
+obj-y += core-dc233c.o
+obj-y += core-fsf.o
--- /dev/null
+/*
+ * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Open Source and Linux Lab nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <stddef.h>
+#include "cpu.h"
+#include "dyngen-exec.h"
+#include "helper.h"
+#include "qemu-log.h"
+
+enum {
+ TARGET_SYS_exit = 1,
+ TARGET_SYS_read = 3,
+ TARGET_SYS_write = 4,
+ TARGET_SYS_open = 5,
+ TARGET_SYS_close = 6,
+ TARGET_SYS_lseek = 19,
+ TARGET_SYS_select_one = 29,
+
+ TARGET_SYS_argc = 1000,
+ TARGET_SYS_argv_sz = 1001,
+ TARGET_SYS_argv = 1002,
+ TARGET_SYS_memset = 1004,
+};
+
+enum {
+ SELECT_ONE_READ = 1,
+ SELECT_ONE_WRITE = 2,
+ SELECT_ONE_EXCEPT = 3,
+};
+
+void HELPER(simcall)(CPUXtensaState *env)
+{
+ uint32_t *regs = env->regs;
+
+ switch (regs[2]) {
+ case TARGET_SYS_exit:
+ qemu_log("exit(%d) simcall\n", regs[3]);
+ exit(regs[3]);
+ break;
+
+ case TARGET_SYS_read:
+ case TARGET_SYS_write:
+ {
+ bool is_write = regs[2] == TARGET_SYS_write;
+ uint32_t fd = regs[3];
+ uint32_t vaddr = regs[4];
+ uint32_t len = regs[5];
+
+ while (len > 0) {
+ target_phys_addr_t paddr =
+ cpu_get_phys_page_debug(env, vaddr);
+ uint32_t page_left =
+ TARGET_PAGE_SIZE - (vaddr & (TARGET_PAGE_SIZE - 1));
+ uint32_t io_sz = page_left < len ? page_left : len;
+ target_phys_addr_t sz = io_sz;
+ void *buf = cpu_physical_memory_map(paddr, &sz, is_write);
+
+ if (buf) {
+ vaddr += io_sz;
+ len -= io_sz;
+ regs[2] = is_write ?
+ write(fd, buf, io_sz) :
+ read(fd, buf, io_sz);
+ regs[3] = errno;
+ cpu_physical_memory_unmap(buf, sz, is_write, sz);
+ if (regs[2] == -1) {
+ break;
+ }
+ } else {
+ regs[2] = -1;
+ regs[3] = EINVAL;
+ break;
+ }
+ }
+ }
+ break;
+
+ case TARGET_SYS_open:
+ {
+ char name[1024];
+ int rc;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(name); ++i) {
+ rc = cpu_memory_rw_debug(
+ env, regs[3] + i, (uint8_t *)name + i, 1, 0);
+ if (rc != 0 || name[i] == 0) {
+ break;
+ }
+ }
+
+ if (rc == 0 && i < ARRAY_SIZE(name)) {
+ regs[2] = open(name, regs[4], regs[5]);
+ regs[3] = errno;
+ } else {
+ regs[2] = -1;
+ regs[3] = EINVAL;
+ }
+ }
+ break;
+
+ case TARGET_SYS_close:
+ if (regs[3] < 3) {
+ regs[2] = regs[3] = 0;
+ } else {
+ regs[2] = close(regs[3]);
+ regs[3] = errno;
+ }
+ break;
+
+ case TARGET_SYS_lseek:
+ regs[2] = lseek(regs[3], (off_t)(int32_t)regs[4], regs[5]);
+ regs[3] = errno;
+ break;
+
+ case TARGET_SYS_select_one:
+ {
+ uint32_t fd = regs[3];
+ uint32_t rq = regs[4];
+ uint32_t target_tv = regs[5];
+ uint32_t target_tvv[2];
+
+ struct timeval tv = {0};
+ fd_set fdset;
+
+ FD_ZERO(&fdset);
+ FD_SET(fd, &fdset);
+
+ if (target_tv) {
+ cpu_memory_rw_debug(env, target_tv,
+ (uint8_t *)target_tvv, sizeof(target_tvv), 0);
+ tv.tv_sec = (int32_t)tswap32(target_tvv[0]);
+ tv.tv_usec = (int32_t)tswap32(target_tvv[1]);
+ }
+ regs[2] = select(fd + 1,
+ rq == SELECT_ONE_READ ? &fdset : NULL,
+ rq == SELECT_ONE_WRITE ? &fdset : NULL,
+ rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
+ target_tv ? &tv : NULL);
+ regs[3] = errno;
+ }
+ break;
+
+ case TARGET_SYS_argc:
+ regs[2] = 1;
+ regs[3] = 0;
+ break;
+
+ case TARGET_SYS_argv_sz:
+ regs[2] = 128;
+ regs[3] = 0;
+ break;
+
+ case TARGET_SYS_argv:
+ {
+ struct Argv {
+ uint32_t argptr[2];
+ char text[120];
+ } argv = {
+ {0, 0},
+ "test"
+ };
+
+ argv.argptr[0] = tswap32(regs[3] + offsetof(struct Argv, text));
+ cpu_memory_rw_debug(
+ env, regs[3], (uint8_t *)&argv, sizeof(argv), 1);
+ }
+ break;
+
+ case TARGET_SYS_memset:
+ {
+ uint32_t base = regs[3];
+ uint32_t sz = regs[5];
+
+ while (sz) {
+ target_phys_addr_t len = sz;
+ void *buf = cpu_physical_memory_map(base, &len, 1);
+
+ if (buf && len) {
+ memset(buf, regs[4], len);
+ cpu_physical_memory_unmap(buf, len, 1, len);
+ } else {
+ len = 1;
+ }
+ base += len;
+ sz -= len;
+ }
+ regs[2] = regs[3];
+ regs[3] = 0;
+ }
+ break;
+
+ default:
+ qemu_log("%s(%d): not implemented\n", __func__, regs[2]);
+ break;
+ }
+}
+++ /dev/null
-/*
- * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the Open Source and Linux Lab nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <stddef.h>
-#include "cpu.h"
-#include "dyngen-exec.h"
-#include "helper.h"
-#include "qemu-log.h"
-
-enum {
- TARGET_SYS_exit = 1,
- TARGET_SYS_read = 3,
- TARGET_SYS_write = 4,
- TARGET_SYS_open = 5,
- TARGET_SYS_close = 6,
- TARGET_SYS_lseek = 19,
- TARGET_SYS_select_one = 29,
-
- TARGET_SYS_argc = 1000,
- TARGET_SYS_argv_sz = 1001,
- TARGET_SYS_argv = 1002,
- TARGET_SYS_memset = 1004,
-};
-
-enum {
- SELECT_ONE_READ = 1,
- SELECT_ONE_WRITE = 2,
- SELECT_ONE_EXCEPT = 3,
-};
-
-void HELPER(simcall)(CPUXtensaState *env)
-{
- uint32_t *regs = env->regs;
-
- switch (regs[2]) {
- case TARGET_SYS_exit:
- qemu_log("exit(%d) simcall\n", regs[3]);
- exit(regs[3]);
- break;
-
- case TARGET_SYS_read:
- case TARGET_SYS_write:
- {
- bool is_write = regs[2] == TARGET_SYS_write;
- uint32_t fd = regs[3];
- uint32_t vaddr = regs[4];
- uint32_t len = regs[5];
-
- while (len > 0) {
- target_phys_addr_t paddr =
- cpu_get_phys_page_debug(env, vaddr);
- uint32_t page_left =
- TARGET_PAGE_SIZE - (vaddr & (TARGET_PAGE_SIZE - 1));
- uint32_t io_sz = page_left < len ? page_left : len;
- target_phys_addr_t sz = io_sz;
- void *buf = cpu_physical_memory_map(paddr, &sz, is_write);
-
- if (buf) {
- vaddr += io_sz;
- len -= io_sz;
- regs[2] = is_write ?
- write(fd, buf, io_sz) :
- read(fd, buf, io_sz);
- regs[3] = errno;
- cpu_physical_memory_unmap(buf, sz, is_write, sz);
- if (regs[2] == -1) {
- break;
- }
- } else {
- regs[2] = -1;
- regs[3] = EINVAL;
- break;
- }
- }
- }
- break;
-
- case TARGET_SYS_open:
- {
- char name[1024];
- int rc;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(name); ++i) {
- rc = cpu_memory_rw_debug(
- env, regs[3] + i, (uint8_t *)name + i, 1, 0);
- if (rc != 0 || name[i] == 0) {
- break;
- }
- }
-
- if (rc == 0 && i < ARRAY_SIZE(name)) {
- regs[2] = open(name, regs[4], regs[5]);
- regs[3] = errno;
- } else {
- regs[2] = -1;
- regs[3] = EINVAL;
- }
- }
- break;
-
- case TARGET_SYS_close:
- if (regs[3] < 3) {
- regs[2] = regs[3] = 0;
- } else {
- regs[2] = close(regs[3]);
- regs[3] = errno;
- }
- break;
-
- case TARGET_SYS_lseek:
- regs[2] = lseek(regs[3], (off_t)(int32_t)regs[4], regs[5]);
- regs[3] = errno;
- break;
-
- case TARGET_SYS_select_one:
- {
- uint32_t fd = regs[3];
- uint32_t rq = regs[4];
- uint32_t target_tv = regs[5];
- uint32_t target_tvv[2];
-
- struct timeval tv = {0};
- fd_set fdset;
-
- FD_ZERO(&fdset);
- FD_SET(fd, &fdset);
-
- if (target_tv) {
- cpu_memory_rw_debug(env, target_tv,
- (uint8_t *)target_tvv, sizeof(target_tvv), 0);
- tv.tv_sec = (int32_t)tswap32(target_tvv[0]);
- tv.tv_usec = (int32_t)tswap32(target_tvv[1]);
- }
- regs[2] = select(fd + 1,
- rq == SELECT_ONE_READ ? &fdset : NULL,
- rq == SELECT_ONE_WRITE ? &fdset : NULL,
- rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
- target_tv ? &tv : NULL);
- regs[3] = errno;
- }
- break;
-
- case TARGET_SYS_argc:
- regs[2] = 1;
- regs[3] = 0;
- break;
-
- case TARGET_SYS_argv_sz:
- regs[2] = 128;
- regs[3] = 0;
- break;
-
- case TARGET_SYS_argv:
- {
- struct Argv {
- uint32_t argptr[2];
- char text[120];
- } argv = {
- {0, 0},
- "test"
- };
-
- argv.argptr[0] = tswap32(regs[3] + offsetof(struct Argv, text));
- cpu_memory_rw_debug(
- env, regs[3], (uint8_t *)&argv, sizeof(argv), 1);
- }
- break;
-
- case TARGET_SYS_memset:
- {
- uint32_t base = regs[3];
- uint32_t sz = regs[5];
-
- while (sz) {
- target_phys_addr_t len = sz;
- void *buf = cpu_physical_memory_map(base, &len, 1);
-
- if (buf && len) {
- memset(buf, regs[4], len);
- cpu_physical_memory_unmap(buf, len, 1, len);
- } else {
- len = 1;
- }
- base += len;
- sz -= len;
- }
- regs[2] = regs[3];
- regs[3] = 0;
- }
- break;
-
- default:
- qemu_log("%s(%d): not implemented\n", __func__, regs[2]);
- break;
- }
-}