diff --git a/RUNNING.md b/RUNNING.md index 8a2b826a44d5..fcd7cab0aede 100644 --- a/RUNNING.md +++ b/RUNNING.md @@ -26,6 +26,7 @@ cd build # On Intel Macs ../configure --target-list=arm-softmmu --extra-cflags=-I/usr/local/opt/openssl@3/include --extra-ldflags='-L/usr/local/opt/openssl@3/lib -lcrypto' + # On Apple Silicon Macs ../configure --enable-sdl --disable-cocoa --target-list=arm-softmmu --disable-capstone --disable-pie --disable-slirp --extra-cflags=-I/opt/homebrew/opt/openssl@3/include --extra-ldflags='-L/opt/homebrew/opt/openssl@3/lib -lcrypto' diff --git a/configs/devices/arm-softmmu/default.mak b/configs/devices/arm-softmmu/default.mak index cc6d134d1618..8af2ed45e080 100644 --- a/configs/devices/arm-softmmu/default.mak +++ b/configs/devices/arm-softmmu/default.mak @@ -4,7 +4,6 @@ # CONFIG_TEST_DEVICES=n CONFIG_ARM_VIRT=y - # These are selected by default when TCG is enabled, uncomment them to # keep out of the build. # CONFIG_CUBIEBOARD=n @@ -45,3 +44,4 @@ CONFIG_ARM_VIRT=y # CONFIG_FSL_IMX6UL=n # CONFIG_ALLWINNER_H3=n CONFIG_IPOD_TOUCH_2G=y + diff --git a/hw/arm/guest-fds.c b/hw/arm/guest-fds.c new file mode 100644 index 000000000000..f1094432c211 --- /dev/null +++ b/hw/arm/guest-fds.c @@ -0,0 +1,72 @@ +/* + * QEMU TCP Tunnelling + * + * Copyright (c) 2019 Lev Aronsky + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without retvaltriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPretvalS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#include "hw/arm/guest-services/fds.h" +#include "cpu.h" + +int32_t guest_svcs_fds[MAX_FD_COUNT] = { [0 ... MAX_FD_COUNT-1] = -1 }; + +int32_t qc_handle_close(CPUState *cpu, int32_t fd) +{ + VERIFY_FD(fd); + + int retval = -1; + + if ((retval = close(guest_svcs_fds[fd])) < 0) { + guest_svcs_errno = errno; + } else { + // TODO: should this be in the "else" clause, or performed regardless? + guest_svcs_fds[fd] = -1; + } + + return retval; +} + +int32_t qc_handle_fcntl_getfl(CPUState *cpu, int32_t fd) +{ + VERIFY_FD(fd); + + int retval = -1; + + if ((retval = fcntl(guest_svcs_fds[fd], F_GETFL)) < 0) { + guest_svcs_errno = errno; + } + + return retval; +} + +int32_t qc_handle_fcntl_setfl(CPUState *cpu, int32_t fd, int32_t flags) +{ + VERIFY_FD(fd); + + int retval = -1; + + if ((retval = fcntl(guest_svcs_fds[fd], F_SETFL, flags)) < 0) { + guest_svcs_errno = errno; + } + + return retval; +} diff --git a/hw/arm/guest-file.c b/hw/arm/guest-file.c new file mode 100644 index 000000000000..f9f4709769a5 --- /dev/null +++ b/hw/arm/guest-file.c @@ -0,0 +1,111 @@ +/* + * QEMU Host file guest access + * + * Copyright (c) 2020 Jonathan Afek + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw/arm/guest-services/file.h" +#include "cpu.h" + +static int32_t file_fds[MAX_FILE_FDS] = { [0 ... MAX_FILE_FDS-1] = -1 }; + +void qc_file_open(uint64_t index, const char *filename) +{ + if (index >= MAX_FILE_FDS) { + abort(); + } + if (-1 != file_fds[index]) { + abort(); + } + file_fds[index] = open(filename, O_RDWR); + if (-1 == file_fds[index]) { + abort(); + } +} + +int64_t qc_handle_write_file(CPUState *cpu, uint64_t buffer_guest_ptr, + uint64_t length, uint64_t offset, uint64_t index) +{ + uint8_t buf[MAX_FILE_TRANSACTION_LEN]; + + if (index >= MAX_FILE_FDS) { + abort(); + } + int fd = file_fds[index]; + if (-1 == fd) { + abort(); + } + if (offset != lseek(fd, offset, SEEK_SET)) { + abort(); + } + if (length > MAX_FILE_TRANSACTION_LEN) { + abort(); + } + cpu_memory_rw_debug(cpu, buffer_guest_ptr, &buf[0], length, 0); + if (length != write(fd, &buf[0], length)) { + abort(); + } + + return 0; +} + +int64_t qc_handle_read_file(CPUState *cpu, uint64_t buffer_guest_ptr, + uint64_t length, uint64_t offset, uint64_t index) +{ + uint8_t buf[MAX_FILE_TRANSACTION_LEN]; + if (index >= MAX_FILE_FDS) { + abort(); + } + int fd = file_fds[index]; + if (-1 == fd) { + abort(); + } + if (offset != lseek(fd, offset, SEEK_SET)) { + abort(); + } + if (length > MAX_FILE_TRANSACTION_LEN) { + abort(); + } + if (length != read(fd, &buf[0], length)) { + abort(); + } + cpu_memory_rw_debug(cpu, buffer_guest_ptr, &buf[0], length, 1); + + return 0; +} + +int64_t qc_handle_size_file(uint64_t index) +{ + struct stat st; + + if (index >= MAX_FILE_FDS) { + abort(); + } + int fd = file_fds[index]; + if (-1 == fd) { + abort(); + } + if (-1 == fstat(fd, &st)) { + abort(); + } + + return st.st_size; +} diff --git a/hw/arm/guest-services.c b/hw/arm/guest-services.c new file mode 100644 index 000000000000..078369e9cc73 --- /dev/null +++ b/hw/arm/guest-services.c @@ -0,0 +1,178 @@ +/* + * QEMU TCP Tunnelling + * + * Copyright (c) 2019 Lev Aronsky + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/arm/boot.h" +#include "exec/address-spaces.h" +#include "hw/misc/unimp.h" +#include "sysemu/sysemu.h" +#include "qemu/error-report.h" +#include "hw/platform-bus.h" +#include "hw/arm/ipod_touch_2g.h" +#include "cpu.h" + +int32_t guest_svcs_errno = 0; + +uint32_t qemu_call_status(CPUARMState *env) +{ + // NOT USED FOR NOW + return 0; +} + +void qemu_call(CPUARMState *env, uint32_t value) +{ + CPUState *cpu = qemu_get_cpu(0); + qemu_call_t qcall; + uint64_t i = 0; + +/* static uint8_t hooks_installed = false; + + if (!value) { + // Special case: not a regular QEMU call. This is used by our + // kernel task port patch to notify of the readiness for the + // hook installation. + + IPodTouchMachineState *nms = IPOD_TOUCH_MACHINE(qdev_get_machine()); + KernelTrHookParams *hook = &nms->hook; + + if (0 != hook->va) { + //install the hook here because we need the MMU to be already + //configured and all the memory mapped before installing the hook + xnu_hook_tr_copy_install(hook->va, hook->pa, hook->buf_va, + hook->buf_pa, hook->code, hook->code_size, + hook->buf_size, hook->scratch_reg); + + } + + if (!hooks_installed) { + for (i = 0; i < nms->hook_funcs_count; i++) { + xnu_hook_tr_copy_install(nms->hook_funcs[i].va, + nms->hook_funcs[i].pa, + nms->hook_funcs[i].buf_va, + nms->hook_funcs[i].buf_pa, + nms->hook_funcs[i].code, + nms->hook_funcs[i].code_size, + nms->hook_funcs[i].buf_size, + nms->hook_funcs[i].scratch_reg); + } + hooks_installed = true; + } + + //emulate original opcode: str x20, [x23] + value = env->xregs[20]; + cpu_memory_rw_debug(cpu, env->xregs[23], (uint8_t*) &value, + sizeof(value), 1); + + return; + } + */ + // Read the request + cpu_memory_rw_debug(cpu, value, (uint8_t*) &qcall, sizeof(qcall), 0); + + switch (qcall.call_number) { + // File Descriptors + case QC_CLOSE: + qcall.retval = qc_handle_close(cpu, qcall.args.close.fd); + break; + case QC_FCNTL: + switch (qcall.args.fcntl.cmd) { + case F_GETFL: + qcall.retval = qc_handle_fcntl_getfl( + cpu, qcall.args.fcntl.fd); + break; + case F_SETFL: + qcall.retval = qc_handle_fcntl_setfl( + cpu, qcall.args.fcntl.fd, qcall.args.fcntl.flags); + break; + default: + guest_svcs_errno = EINVAL; + qcall.retval = -1; + } + break; + + // Socket API + case QC_SOCKET: + qcall.retval = qc_handle_socket(cpu, qcall.args.socket.domain, + qcall.args.socket.type, + qcall.args.socket.protocol); + break; + case QC_ACCEPT: + qcall.retval = qc_handle_accept(cpu, qcall.args.accept.socket, + qcall.args.accept.addr, + qcall.args.accept.addrlen); + break; + case QC_BIND: + qcall.retval = qc_handle_bind(cpu, qcall.args.bind.socket, + qcall.args.bind.addr, + qcall.args.bind.addrlen); + break; + case QC_CONNECT: + qcall.retval = qc_handle_connect(cpu, qcall.args.connect.socket, + qcall.args.connect.addr, + qcall.args.connect.addrlen); + break; + case QC_LISTEN: + qcall.retval = qc_handle_listen(cpu, qcall.args.listen.socket, + qcall.args.listen.backlog); + break; + case QC_RECV: + qcall.retval = qc_handle_recv(cpu, qcall.args.recv.socket, + qcall.args.recv.buffer, + qcall.args.recv.length, + qcall.args.recv.flags); + break; + case QC_SEND: + qcall.retval = qc_handle_send(cpu, qcall.args.send.socket, + qcall.args.send.buffer, + qcall.args.send.length, + qcall.args.send.flags); + break; + case QC_WRITE_FILE: + qcall.retval = qc_handle_write_file(cpu, + qcall.args.write_file.buffer_guest_ptr, + qcall.args.write_file.length, + qcall.args.write_file.offset, + qcall.args.write_file.index); + break; + case QC_READ_FILE: + qcall.retval = qc_handle_read_file(cpu, + qcall.args.read_file.buffer_guest_ptr, + qcall.args.read_file.length, + qcall.args.read_file.offset, + qcall.args.read_file.index); + break; + case QC_SIZE_FILE: + qcall.retval = qc_handle_size_file(qcall.args.size_file.index); + break; + default: + // TODO: handle unknown call numbers + break; + } + + qcall.error = guest_svcs_errno; + + // Write the response + cpu_memory_rw_debug(cpu, value, (uint8_t*) &qcall, sizeof(qcall), 1); +} diff --git a/hw/arm/guest-socket.c b/hw/arm/guest-socket.c new file mode 100644 index 000000000000..fdf9d1e2df0c --- /dev/null +++ b/hw/arm/guest-socket.c @@ -0,0 +1,192 @@ +/* + * QEMU TCP Tunnelling + * + * Copyright (c) 2019 Lev Aronsky + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without retvaltriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPretvalS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw/arm/guest-services/socket.h" +#include "hw/arm/guest-services/fds.h" +#include "sys/socket.h" +#include "cpu.h" + +#define SOCKET_TIMEOUT_USECS (10) + +static int32_t find_free_socket(void) { + for (int i = 0; i < MAX_FD_COUNT; ++i) { + if (-1 == guest_svcs_fds[i]) { + return i; + } + } + + guest_svcs_errno = ENOMEM; + return -1; +} + +int32_t qc_handle_socket(CPUState *cpu, int32_t domain, int32_t type, + int32_t protocol) +{ + int retval = find_free_socket(); + + if (retval < 0) { + guest_svcs_errno = ENOTSOCK; + } else if ((guest_svcs_fds[retval] = socket(domain, type, protocol)) < 0) { + retval = -1; + guest_svcs_errno = errno; + } + + return retval; +} + +int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, struct sockaddr *g_addr, + socklen_t *g_addrlen) +{ + struct sockaddr_in addr; + socklen_t addrlen; + + VERIFY_FD(sckt); + + int retval = find_free_socket(); + + // TODO: timeout + if (retval < 0) { + guest_svcs_errno = ENOTSOCK; + } else if ((guest_svcs_fds[retval] = accept(guest_svcs_fds[sckt], + (struct sockaddr *) &addr, + &addrlen)) < 0) { + retval = -1; + guest_svcs_errno = errno; + } else { + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, + sizeof(addr), 1); + cpu_memory_rw_debug(cpu, (target_ulong) g_addrlen, + (uint8_t*) &addrlen, sizeof(addrlen), 1); + } + + return retval; +} + +int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, struct sockaddr *g_addr, + socklen_t addrlen) +{ + struct sockaddr_in addr; + + VERIFY_FD(sckt); + + int retval = 0; + + if (addrlen > sizeof(addr)) { + guest_svcs_errno = ENOMEM; + } else { + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, + sizeof(addr), 0); + + if ((retval = bind(guest_svcs_fds[sckt], (struct sockaddr *) &addr, + addrlen)) < 0) { + guest_svcs_errno = errno; + } else { + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, + sizeof(addr), 1); + } + } + + return retval; +} + +int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, struct sockaddr *g_addr, + socklen_t addrlen) +{ + struct sockaddr_in addr; + + VERIFY_FD(sckt); + + int retval = 0; + + if (addrlen > sizeof(addr)) { + guest_svcs_errno = ENOMEM; + } else { + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, + sizeof(addr), 0); + + if ((retval = connect(guest_svcs_fds[sckt], (struct sockaddr *) &addr, + addrlen)) < 0) { + guest_svcs_errno = errno; + } else { + cpu_memory_rw_debug(cpu, (target_ulong) g_addr, (uint8_t*) &addr, + sizeof(addr), 1); + } + } + + return retval; +} + +int32_t qc_handle_listen(CPUState *cpu, int32_t sckt, int32_t backlog) +{ + VERIFY_FD(sckt); + + int retval = 0; + + if ((retval = listen(guest_svcs_fds[sckt], backlog)) < 0) { + guest_svcs_errno = errno; + } + + return retval; +} + +int32_t qc_handle_recv(CPUState *cpu, int32_t sckt, void *g_buffer, + size_t length, int32_t flags) +{ + VERIFY_FD(sckt); + uint8_t buffer[MAX_BUF_SIZE]; + + int retval = -1; + + // TODO: timeout + if (length > MAX_BUF_SIZE) { + guest_svcs_errno = ENOMEM; + } else if ((retval = recv(guest_svcs_fds[sckt], buffer, length, flags)) <= 0) { + guest_svcs_errno = errno; + } else { + cpu_memory_rw_debug(cpu, (target_ulong) g_buffer, buffer, retval, 1); + } + + return retval; +} + +int32_t qc_handle_send(CPUState *cpu, int32_t sckt, void *g_buffer, + size_t length, int32_t flags) +{ + VERIFY_FD(sckt); + uint8_t buffer[MAX_BUF_SIZE]; + + int retval = -1; + + if (length > MAX_BUF_SIZE) { + guest_svcs_errno = ENOMEM; + } else { + cpu_memory_rw_debug(cpu, (target_ulong) g_buffer, buffer, length, 0); + + if ((retval = send(guest_svcs_fds[sckt], buffer, length, flags)) < 0) { + guest_svcs_errno = errno; + } + } + + return retval; +} diff --git a/hw/arm/ipod_touch_2g.c b/hw/arm/ipod_touch_2g.c index c0d4724681e9..ee9b39b401e1 100644 --- a/hw/arm/ipod_touch_2g.c +++ b/hw/arm/ipod_touch_2g.c @@ -12,8 +12,10 @@ #include "hw/arm/exynos4210.h" #include "hw/arm/ipod_touch_2g.h" #include "target/arm/cpregs.h" + #include "qemu/error-report.h" + #define VMSTATE_IT2G_CPREG(name) \ VMSTATE_UINT64(IT2G_CPREG_VAR_NAME(name), IPodTouchMachineState) @@ -27,6 +29,29 @@ - offsetof(ARMCPU, env) \ } + +#define IT2G_CPREG_DEF_QEMU_CALL \ + { \ + .cp = 15, \ + .name = "QEMU_CALL", \ + .opc0 = 0, \ + .opc1 = 3, \ + .crn = 15, \ + .crm = 15, \ + .opc2 = 0, \ + .access = PL0_RW, \ + .resetvalue = 0, \ + .state = ARM_CP_STATE_AA32, \ + .type = ARM_CP_IO, \ + .fieldoffset = offsetof(IPodTouchMachineState, IT2G_CPREG_VAR_NAME(QEMU_CALL)) \ + - offsetof(ARMCPU, env), \ + .readfn = qemu_call_status, \ + .writefn = qemu_call, \ + } + +const int S5L8900_GPIO_IRQS[5] = { S5L8900_GPIO_G0_IRQ, S5L8900_GPIO_G1_IRQ, S5L8900_GPIO_G2_IRQ, S5L8900_GPIO_G3_IRQ, S5L8900_GPIO_G4_IRQ }; + + static void allocate_ram(MemoryRegion *top, const char *name, uint32_t addr, uint32_t size) { MemoryRegion *sec = g_new(MemoryRegion, 1); @@ -39,6 +64,7 @@ static const ARMCPRegInfo it2g_cp_reginfo_tcg[] = { IT2G_CPREG_DEF(REG1, 0, 0, 15, 2, 4, PL1_RW, 0), IT2G_CPREG_DEF(REG1, 0, 0, 7, 14, 0, PL1_RW, 0), IT2G_CPREG_DEF(REG1, 0, 0, 7, 10, 0, PL1_RW, 0), + IT2G_CPREG_DEF_QEMU_CALL, }; static void ipod_touch_cpu_setup(MachineState *machine, MemoryRegion **sysmem, ARMCPU **cpu, AddressSpace **nsas) @@ -532,4 +558,5 @@ static void ipod_touch_machine_types(void) type_register_static(&ipod_touch_machine_info); } -type_init(ipod_touch_machine_types) \ No newline at end of file + +type_init(ipod_touch_machine_types) diff --git a/hw/arm/ipod_touch_usb_otg.c b/hw/arm/ipod_touch_usb_otg.c index d2ca30e33bfd..e36f7cb6dca9 100644 --- a/hw/arm/ipod_touch_usb_otg.c +++ b/hw/arm/ipod_touch_usb_otg.c @@ -134,6 +134,7 @@ static uint32_t synopsys_usb_in_ep_read(synopsys_usb_state *_state, uint8_t _ep, default: hw_error("usb_synopsys: bad ep read offset 0x" HWADDR_FMT_plx "\n", _addr); + break; } @@ -308,7 +309,7 @@ static void synopsys_usb_in_ep_write(synopsys_usb_state *_state, int _ep, hwaddr return; default: - hw_error("usb_synopsys: bad ep write offset 0x" HWADDR_FMT_plx "\n", _addr); + hw_error("usb_synopsys: bad ep write offset 0x" TARGET_FMT_plx "\n", _addr); break; } } diff --git a/hw/arm/meson.build b/hw/arm/meson.build index b642f3857f3a..4f318b82a19d 100644 --- a/hw/arm/meson.build +++ b/hw/arm/meson.build @@ -64,12 +64,10 @@ arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre. arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c')) arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c')) arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c')) +arm_ss.add(when: 'CONFIG_IPOD_TOUCH_2G', if_true: files('ipod_touch_2g.c', 'ipod_touch_clock.c', 'ipod_touch_chipid.c', 'ipod_touch_gpio.c','guest-services.c', 'guest-socket.c', 'guest-fds.c', 'guest-file.c', 'ipod_touch_sysic.c', 'ipod_touch_timer.c', 'ipod_touch_usb_otg.c', 'ipod_touch_usb_phys.c', 'ipod_touch_spi.c', 'ipod_touch_nor_spi.c', 'ipod_touch_sha1.c', 'ipod_touch_aes.c', 'ipod_touch_pke.c', 'ipod_touch_pcf50633_pmu.c', 'ipod_touch_unknown1.c', 'ipod_touch_lcd.c', 'ipod_touch_mipi_dsi.c', 'ipod_touch_fmss.c', 'ipod_touch_mbx.c', 'ipod_touch_cd3272_mikey.c', 'ipod_touch_lis302dl.c', 'ipod_touch_multitouch.c', 'ipod_touch_scaler_csc.c', 'ipod_touch_sdio.c', 'ipod_touch_tvout.c')) arm_ss.add(when: 'CONFIG_XEN', if_true: files('xen_arm.c')) -arm_ss.add(when: 'CONFIG_IPOD_TOUCH_2G', if_true: files('ipod_touch_2g.c', 'ipod_touch_clock.c', 'ipod_touch_chipid.c', 'ipod_touch_gpio.c', 'ipod_touch_sysic.c', 'ipod_touch_timer.c', 'ipod_touch_usb_otg.c', 'ipod_touch_usb_phys.c', 'ipod_touch_spi.c', 'ipod_touch_nor_spi.c', 'ipod_touch_sha1.c', 'ipod_touch_aes.c', 'ipod_touch_pke.c', 'ipod_touch_pcf50633_pmu.c', 'ipod_touch_unknown1.c', 'ipod_touch_lcd.c', 'ipod_touch_mipi_dsi.c', 'ipod_touch_fmss.c', 'ipod_touch_mbx.c', 'ipod_touch_cd3272_mikey.c', 'ipod_touch_lis302dl.c', 'ipod_touch_multitouch.c', 'ipod_touch_scaler_csc.c', 'ipod_touch_sdio.c', 'ipod_touch_tvout.c')) - system_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c')) system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4_boards.c')) system_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_peripherals.c')) system_ss.add(when: 'CONFIG_TOSA', if_true: files('tosa.c')) - hw_arch += {'arm': arm_ss} diff --git a/hw/intc/meson.build b/hw/intc/meson.build index 1c3d0d6eee67..6d4732dc84aa 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -12,6 +12,7 @@ system_ss.add(when: 'CONFIG_ARM_GICV3_TCG', if_true: files( 'arm_gicv3_its.c', 'arm_gicv3_redist.c', )) + system_ss.add(when: 'CONFIG_ALLWINNER_A10_PIC', if_true: files('allwinner-a10-pic.c')) system_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_vic.c')) system_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_pic.c')) @@ -38,6 +39,7 @@ if config_all_devices.has_key('CONFIG_APIC') or \ system_ss.add(files('kvm_irqcount.c')) endif + specific_ss.add(when: 'CONFIG_APIC', if_true: files('apic.c', 'apic_common.c')) specific_ss.add(when: 'CONFIG_ARM_GIC', if_true: files('arm_gicv3_cpuif_common.c')) specific_ss.add(when: 'CONFIG_ARM_GICV3_TCG', if_true: files('arm_gicv3_cpuif.c')) diff --git a/hw/intc/pl192.c b/hw/intc/pl192.c index 911abc061588..e29953f44629 100644 --- a/hw/intc/pl192.c +++ b/hw/intc/pl192.c @@ -330,6 +330,7 @@ static void pl192_write(void *opaque, hwaddr offset, uint64_t value, unsigned si return; default: fprintf(stderr, "pl192: bad write offset (2) " HWADDR_FMT_plx "\n", offset); + return; } diff --git a/include/hw/arm/guest-services/fds.h b/include/hw/arm/guest-services/fds.h new file mode 100644 index 000000000000..83a415c34375 --- /dev/null +++ b/include/hw/arm/guest-services/fds.h @@ -0,0 +1,67 @@ +/* + * QEMU TCP Tunnelling + * + * Copyright (c) 2019 Lev Aronsky + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_ARM_GUEST_SERVICES_FDS_H +#define HW_ARM_GUEST_SERVICES_FDS_H + +#ifndef OUT_OF_TREE_BUILD +#include "qemu/osdep.h" +#else +#include "sys/types.h" +#include "sys/socket.h" +#endif + +#define MAX_FD_COUNT (256) + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +extern int32_t guest_svcs_errno; +#pragma GCC diagnostic pop +extern int32_t guest_svcs_fds[MAX_FD_COUNT]; + +#define VERIFY_FD(s) \ + if ((s < 0) || (s >= MAX_FD_COUNT) || (-1 == guest_svcs_fds[s])) return -1; + +typedef struct __attribute__((packed)) { + int32_t fd; +} qc_close_args_t; + +typedef struct __attribute__((packed)) { + int32_t fd; + int32_t cmd; + union { + int32_t flags; + }; +} qc_fcntl_args_t; + +#ifndef OUT_OF_TREE_BUILD +int32_t qc_handle_close(CPUState *cpu, int32_t fd); +int32_t qc_handle_fcntl_getfl(CPUState *cpu, int32_t fd); +int32_t qc_handle_fcntl_setfl(CPUState *cpu, int32_t fd, int32_t flags); +#else +int qc_close(int fd); +int qc_fcntl(int fd, int cmd, ...); +#endif + +#endif // HW_ARM_GUEST_SERVICES_FDS_H diff --git a/include/hw/arm/guest-services/file.h b/include/hw/arm/guest-services/file.h new file mode 100644 index 000000000000..bd885913d5c0 --- /dev/null +++ b/include/hw/arm/guest-services/file.h @@ -0,0 +1,69 @@ +/* + * QEMU Host file guest access + * + * Copyright (c) 2020 Jonathan Afek + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_ARM_GUEST_SERVICES_FILE_H +#define HW_ARM_GUEST_SERVICES_FILE_H + +#ifndef OUT_OF_TREE_BUILD +#include "qemu/osdep.h" +#else +#include "sys/types.h" +#endif + +#define MAX_FILE_FDS (8) +#define MAX_FILE_TRANSACTION_LEN (0x2000) + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +extern int32_t guest_svcs_errno; +#pragma GCC diagnostic pop + +typedef struct __attribute__((packed)) { + uint64_t buffer_guest_ptr; + uint64_t length; + uint64_t offset; + uint64_t index; +} qc_write_file_args_t, qc_read_file_args_t; + +typedef struct __attribute__((packed)) { + uint64_t index; +} qc_size_file_args_t; + +#ifndef OUT_OF_TREE_BUILD +void qc_file_open(uint64_t index, const char *filename); + +int64_t qc_handle_write_file(CPUState *cpu, uint64_t buffer_guest_ptr, + uint64_t length, uint64_t offset, uint64_t index); +int64_t qc_handle_read_file(CPUState *cpu, uint64_t buffer_guest_ptr, + uint64_t length, uint64_t offset, uint64_t index); +int64_t qc_handle_size_file(uint64_t index); +#else +int64_t qc_write_file(void *buffer_guest_ptr, uint64_t length, + uint64_t offset, uint64_t index); +int64_t qc_read_file(void *buffer_guest_ptr, uint64_t length, + uint64_t offset, uint64_t index); +int64_t qc_size_file(uint64_t index); +#endif + +#endif diff --git a/include/hw/arm/guest-services/general.h b/include/hw/arm/guest-services/general.h new file mode 100644 index 000000000000..34c6229dab14 --- /dev/null +++ b/include/hw/arm/guest-services/general.h @@ -0,0 +1,88 @@ +/* + * QEMU TCP Tunnelling + * + * Copyright (c) 2019 Lev Aronsky + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_ARM_GUEST_SERVICES_GENERAL_H +#define HW_ARM_GUEST_SERVICES_GENERAL_H + +#include "hw/arm/guest-services/socket.h" +#include "hw/arm/guest-services/fds.h" +#include "hw/arm/guest-services/file.h" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +extern int32_t guest_svcs_errno; +#pragma GCC diagnostic pop + +typedef enum { + // File Descriptors API + QC_CLOSE = 0x100, + QC_FCNTL, + + // Socket API + QC_SOCKET = 0x110, + QC_ACCEPT, + QC_BIND, + QC_CONNECT, + QC_LISTEN, + QC_RECV, + QC_SEND, + QC_WRITE_FILE, + QC_READ_FILE, + QC_SIZE_FILE, +} qemu_call_number_t; + +typedef struct __attribute__((packed)) { + // Request + qemu_call_number_t call_number; + union { + // File Descriptors API + qc_close_args_t close; + qc_fcntl_args_t fcntl; + // Socket API + qc_socket_args_t socket; + qc_accept_args_t accept; + qc_bind_args_t bind; + qc_connect_args_t connect; + qc_listen_args_t listen; + qc_recv_args_t recv; + qc_send_args_t send; + qc_write_file_args_t write_file; + qc_read_file_args_t read_file; + qc_size_file_args_t size_file; + } args; + + // Response + int64_t retval; + int64_t error; +} qemu_call_t; + +#ifndef OUT_OF_TREE_BUILD +uint32_t qemu_call_status(CPUARMState *env); +void qemu_call(CPUARMState *env, uint32_t value); +#else +uint32_t qemu_call_status(qemu_call_t *qcall); +void qemu_call(qemu_call_t *qcall); +#endif + +#endif // HW_ARM_GUEST_SERVICES_GENERAL_H diff --git a/include/hw/arm/guest-services/socket.h b/include/hw/arm/guest-services/socket.h new file mode 100644 index 000000000000..ff98bd8b668e --- /dev/null +++ b/include/hw/arm/guest-services/socket.h @@ -0,0 +1,96 @@ +/* + * QEMU TCP Tunnelling + * + * Copyright (c) 2019 Lev Aronsky + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HW_ARM_GUEST_SERVICES_SOCKET_H +#define HW_ARM_GUEST_SERVICES_SOCKET_H + +#ifndef OUT_OF_TREE_BUILD +#include "qemu/osdep.h" +#else +#include "sys/types.h" +#include "sys/socket.h" +#endif + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wredundant-decls" +extern int32_t guest_svcs_errno; +#pragma GCC diagnostic pop + +#define MAX_BUF_SIZE (4096) + +typedef struct __attribute__((packed)) { + int32_t domain; + int32_t type; + int32_t protocol; +} qc_socket_args_t; + +typedef struct __attribute__((packed)) { + int32_t socket; + struct sockaddr *addr; + socklen_t *addrlen; +} qc_accept_args_t; + +typedef struct __attribute__((packed)) { + int32_t socket; + struct sockaddr *addr; + socklen_t addrlen; +} qc_bind_args_t, qc_connect_args_t; + +typedef struct __attribute__((packed)) { + int32_t socket; + int32_t backlog; +} qc_listen_args_t; + +typedef struct __attribute__((packed)) { + int32_t socket; + void *buffer; + size_t length; + int flags; +} qc_recv_args_t, qc_send_args_t; + +#ifndef OUT_OF_TREE_BUILD +int32_t qc_handle_socket(CPUState *cpu, int32_t domain, int32_t type, + int32_t protocol); +int32_t qc_handle_accept(CPUState *cpu, int32_t sckt, struct sockaddr *addr, + socklen_t *addrlen); +int32_t qc_handle_bind(CPUState *cpu, int32_t sckt, struct sockaddr *addr, + socklen_t addrlen); +int32_t qc_handle_connect(CPUState *cpu, int32_t sckt, struct sockaddr *addr, + socklen_t addrlen); +int32_t qc_handle_listen(CPUState *cpu, int32_t sckt, int32_t backlog); +int32_t qc_handle_recv(CPUState *cpu, int32_t sckt, void *buffer, + size_t length, int32_t flags); +int32_t qc_handle_send(CPUState *cpu, int32_t sckt, void *buffer, + size_t length, int32_t flags); +#else +int qc_socket(int domain, int type, int protocol); +int qc_accept(int sckt, struct sockaddr *addr, socklen_t *addrlen); +int qc_bind(int sckt, const struct sockaddr *addr, socklen_t addrlen); +int qc_connect(int sckt, const struct sockaddr *addr, socklen_t addrlen); +int qc_listen(int sckt, int backlog); +ssize_t qc_recv(int sckt, void *buffer, size_t length, int flags); +ssize_t qc_send(int sckt, const void *buffer, size_t length, int flags); +#endif + +#endif // HW_ARM_GUEST_SERVICES_SOCKET_H diff --git a/include/hw/arm/ipod_touch_2g.h b/include/hw/arm/ipod_touch_2g.h index 8f1d87f51776..9c923fc599a3 100644 --- a/include/hw/arm/ipod_touch_2g.h +++ b/include/hw/arm/ipod_touch_2g.h @@ -28,6 +28,8 @@ #include "hw/arm/ipod_touch_scaler_csc.h" #include "hw/arm/ipod_touch_sdio.h" #include "hw/arm/ipod_touch_tvout.h" +#include "hw/arm/guest-services/general.h" + #define TYPE_IPOD_TOUCH "iPod-Touch" @@ -57,7 +59,7 @@ #define S5L8900_GPIO_G3_IRQ 0x03 #define S5L8900_GPIO_G4_IRQ 0x02 -const int S5L8900_GPIO_IRQS[5] = { S5L8900_GPIO_G0_IRQ, S5L8900_GPIO_G1_IRQ, S5L8900_GPIO_G2_IRQ, S5L8900_GPIO_G3_IRQ, S5L8900_GPIO_G4_IRQ }; +extern const int S5L8900_GPIO_IRQS[5]; #define IT2G_CPREG_VAR_NAME(name) cpreg_##name #define IT2G_CPREG_VAR_DEF(name) uint64_t IT2G_CPREG_VAR_NAME(name) @@ -155,6 +157,5 @@ typedef struct { char nand_path[1024]; IT2G_CPREG_VAR_DEF(REG0); IT2G_CPREG_VAR_DEF(REG1); + IT2G_CPREG_VAR_DEF(QEMU_CALL); } IPodTouchMachineState; - -#endif \ No newline at end of file