mirror of https://github.com/xqemu/xqemu.git
Merge branch 'linux-user.next' of git://git.linaro.org/people/pmaydell/qemu-arm
* 'linux-user.next' of git://git.linaro.org/people/pmaydell/qemu-arm: linux-user: ARM: Ignore immediate value for svc in thumb mode linux-user: Use init_guest_space when -R and -B are specified linux-user: Factor out guest space probing into a function flatload: fix bss clearing linux-user: make host_to_target_cmsg support SO_TIMESTAMP cmsg_type linux-user: make do_setsockopt support SOL_RAW ICMP_FILTER socket option linux-user: pass sockaddr from host to target linux-user: Move target_to_host_errno_table[] setup out of ioctl loop linux-user: Fix SNDCTL_DSP_MAP{IN, OUT}BUF ioctl definitions linux-user: Fix incorrect TARGET_BLKBSZGET, TARGET_BLKBSZSET
This commit is contained in:
commit
873359d411
|
@ -332,9 +332,17 @@ enum
|
||||||
ARM_HWCAP_ARM_VFPv3D16 = 1 << 13,
|
ARM_HWCAP_ARM_VFPv3D16 = 1 << 13,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TARGET_HAS_GUEST_VALIDATE_BASE
|
#define TARGET_HAS_VALIDATE_GUEST_SPACE
|
||||||
/* We want the opportunity to check the suggested base */
|
/* Return 1 if the proposed guest space is suitable for the guest.
|
||||||
bool guest_validate_base(unsigned long guest_base)
|
* Return 0 if the proposed guest space isn't suitable, but another
|
||||||
|
* address space should be tried.
|
||||||
|
* Return -1 if there is no way the proposed guest space can be
|
||||||
|
* valid regardless of the base.
|
||||||
|
* The guest code may leave a page mapped and populate it if the
|
||||||
|
* address is suitable.
|
||||||
|
*/
|
||||||
|
static int validate_guest_space(unsigned long guest_base,
|
||||||
|
unsigned long guest_size)
|
||||||
{
|
{
|
||||||
unsigned long real_start, test_page_addr;
|
unsigned long real_start, test_page_addr;
|
||||||
|
|
||||||
|
@ -342,6 +350,15 @@ bool guest_validate_base(unsigned long guest_base)
|
||||||
* commpage at 0xffff0fxx
|
* commpage at 0xffff0fxx
|
||||||
*/
|
*/
|
||||||
test_page_addr = guest_base + (0xffff0f00 & qemu_host_page_mask);
|
test_page_addr = guest_base + (0xffff0f00 & qemu_host_page_mask);
|
||||||
|
|
||||||
|
/* If the commpage lies within the already allocated guest space,
|
||||||
|
* then there is no way we can allocate it.
|
||||||
|
*/
|
||||||
|
if (test_page_addr >= guest_base
|
||||||
|
&& test_page_addr <= (guest_base + guest_size)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Note it needs to be writeable to let us initialise it */
|
/* Note it needs to be writeable to let us initialise it */
|
||||||
real_start = (unsigned long)
|
real_start = (unsigned long)
|
||||||
mmap((void *)test_page_addr, qemu_host_page_size,
|
mmap((void *)test_page_addr, qemu_host_page_size,
|
||||||
|
@ -1418,14 +1435,105 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef TARGET_HAS_GUEST_VALIDATE_BASE
|
#ifndef TARGET_HAS_VALIDATE_GUEST_SPACE
|
||||||
/* If the guest doesn't have a validation function just agree */
|
/* If the guest doesn't have a validation function just agree */
|
||||||
bool guest_validate_base(unsigned long guest_base)
|
static int validate_guest_space(unsigned long guest_base,
|
||||||
|
unsigned long guest_size)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
unsigned long init_guest_space(unsigned long host_start,
|
||||||
|
unsigned long host_size,
|
||||||
|
unsigned long guest_start,
|
||||||
|
bool fixed)
|
||||||
|
{
|
||||||
|
unsigned long current_start, real_start;
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
assert(host_start || host_size);
|
||||||
|
|
||||||
|
/* If just a starting address is given, then just verify that
|
||||||
|
* address. */
|
||||||
|
if (host_start && !host_size) {
|
||||||
|
if (validate_guest_space(host_start, host_size) == 1) {
|
||||||
|
return host_start;
|
||||||
|
} else {
|
||||||
|
return (unsigned long)-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup the initial flags and start address. */
|
||||||
|
current_start = host_start & qemu_host_page_mask;
|
||||||
|
flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
|
||||||
|
if (fixed) {
|
||||||
|
flags |= MAP_FIXED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, a non-zero size region of memory needs to be mapped
|
||||||
|
* and validated. */
|
||||||
|
while (1) {
|
||||||
|
unsigned long real_size = host_size;
|
||||||
|
|
||||||
|
/* Do not use mmap_find_vma here because that is limited to the
|
||||||
|
* guest address space. We are going to make the
|
||||||
|
* guest address space fit whatever we're given.
|
||||||
|
*/
|
||||||
|
real_start = (unsigned long)
|
||||||
|
mmap((void *)current_start, host_size, PROT_NONE, flags, -1, 0);
|
||||||
|
if (real_start == (unsigned long)-1) {
|
||||||
|
return (unsigned long)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure the address is properly aligned. */
|
||||||
|
if (real_start & ~qemu_host_page_mask) {
|
||||||
|
munmap((void *)real_start, host_size);
|
||||||
|
real_size = host_size + qemu_host_page_size;
|
||||||
|
real_start = (unsigned long)
|
||||||
|
mmap((void *)real_start, real_size, PROT_NONE, flags, -1, 0);
|
||||||
|
if (real_start == (unsigned long)-1) {
|
||||||
|
return (unsigned long)-1;
|
||||||
|
}
|
||||||
|
real_start = HOST_PAGE_ALIGN(real_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check to see if the address is valid. */
|
||||||
|
if (!host_start || real_start == current_start) {
|
||||||
|
int valid = validate_guest_space(real_start - guest_start,
|
||||||
|
real_size);
|
||||||
|
if (valid == 1) {
|
||||||
|
break;
|
||||||
|
} else if (valid == -1) {
|
||||||
|
return (unsigned long)-1;
|
||||||
|
}
|
||||||
|
/* valid == 0, so try again. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* That address didn't work. Unmap and try a different one.
|
||||||
|
* The address the host picked because is typically right at
|
||||||
|
* the top of the host address space and leaves the guest with
|
||||||
|
* no usable address space. Resort to a linear search. We
|
||||||
|
* already compensated for mmap_min_addr, so this should not
|
||||||
|
* happen often. Probably means we got unlucky and host
|
||||||
|
* address space randomization put a shared library somewhere
|
||||||
|
* inconvenient.
|
||||||
|
*/
|
||||||
|
munmap((void *)real_start, host_size);
|
||||||
|
current_start += qemu_host_page_size;
|
||||||
|
if (host_start == current_start) {
|
||||||
|
/* Theoretically possible if host doesn't have any suitably
|
||||||
|
* aligned areas. Normally the first mmap will fail.
|
||||||
|
*/
|
||||||
|
return (unsigned long)-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qemu_log("Reserved 0x%lx bytes of guest address space\n", host_size);
|
||||||
|
|
||||||
|
return real_start;
|
||||||
|
}
|
||||||
|
|
||||||
static void probe_guest_base(const char *image_name,
|
static void probe_guest_base(const char *image_name,
|
||||||
abi_ulong loaddr, abi_ulong hiaddr)
|
abi_ulong loaddr, abi_ulong hiaddr)
|
||||||
{
|
{
|
||||||
|
@ -1452,46 +1560,23 @@ static void probe_guest_base(const char *image_name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
host_size = hiaddr - loaddr;
|
host_size = hiaddr - loaddr;
|
||||||
while (1) {
|
|
||||||
/* Do not use mmap_find_vma here because that is limited to the
|
/* Setup the initial guest memory space with ranges gleaned from
|
||||||
guest address space. We are going to make the
|
* the ELF image that is being loaded.
|
||||||
guest address space fit whatever we're given. */
|
*/
|
||||||
real_start = (unsigned long)
|
real_start = init_guest_space(host_start, host_size, loaddr, false);
|
||||||
mmap((void *)host_start, host_size, PROT_NONE,
|
if (real_start == (unsigned long)-1) {
|
||||||
MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);
|
errmsg = "Unable to find space for application";
|
||||||
if (real_start == (unsigned long)-1) {
|
goto exit_errmsg;
|
||||||
goto exit_perror;
|
|
||||||
}
|
|
||||||
guest_base = real_start - loaddr;
|
|
||||||
if ((real_start == host_start) &&
|
|
||||||
guest_validate_base(guest_base)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* That address didn't work. Unmap and try a different one.
|
|
||||||
The address the host picked because is typically right at
|
|
||||||
the top of the host address space and leaves the guest with
|
|
||||||
no usable address space. Resort to a linear search. We
|
|
||||||
already compensated for mmap_min_addr, so this should not
|
|
||||||
happen often. Probably means we got unlucky and host
|
|
||||||
address space randomization put a shared library somewhere
|
|
||||||
inconvenient. */
|
|
||||||
munmap((void *)real_start, host_size);
|
|
||||||
host_start += qemu_host_page_size;
|
|
||||||
if (host_start == loaddr) {
|
|
||||||
/* Theoretically possible if host doesn't have any suitably
|
|
||||||
aligned areas. Normally the first mmap will fail. */
|
|
||||||
errmsg = "Unable to find space for application";
|
|
||||||
goto exit_errmsg;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
guest_base = real_start - loaddr;
|
||||||
|
|
||||||
qemu_log("Relocating guest address space from 0x"
|
qemu_log("Relocating guest address space from 0x"
|
||||||
TARGET_ABI_FMT_lx " to 0x%lx\n",
|
TARGET_ABI_FMT_lx " to 0x%lx\n",
|
||||||
loaddr, real_start);
|
loaddr, real_start);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
exit_perror:
|
|
||||||
errmsg = strerror(errno);
|
|
||||||
exit_errmsg:
|
exit_errmsg:
|
||||||
fprintf(stderr, "%s: %s\n", image_name, errmsg);
|
fprintf(stderr, "%s: %s\n", image_name, errmsg);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|
|
@ -660,7 +660,7 @@ static int load_flat_file(struct linux_binprm * bprm,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* zero the BSS. */
|
/* zero the BSS. */
|
||||||
memset((void *)((unsigned long)datapos + data_len), 0, bss_len);
|
memset(g2h(datapos + data_len), 0, bss_len);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -186,8 +186,8 @@
|
||||||
IOCTL(SNDCTL_DSP_GETISPACE, IOC_R, MK_PTR(MK_STRUCT(STRUCT_audio_buf_info)))
|
IOCTL(SNDCTL_DSP_GETISPACE, IOC_R, MK_PTR(MK_STRUCT(STRUCT_audio_buf_info)))
|
||||||
IOCTL(SNDCTL_DSP_GETOSPACE, IOC_R, MK_PTR(MK_STRUCT(STRUCT_audio_buf_info)))
|
IOCTL(SNDCTL_DSP_GETOSPACE, IOC_R, MK_PTR(MK_STRUCT(STRUCT_audio_buf_info)))
|
||||||
IOCTL(SNDCTL_DSP_GETTRIGGER, IOC_R, MK_PTR(TYPE_INT))
|
IOCTL(SNDCTL_DSP_GETTRIGGER, IOC_R, MK_PTR(TYPE_INT))
|
||||||
IOCTL(SNDCTL_DSP_MAPINBUF, IOC_R, MK_PTR(TYPE_INT))
|
IOCTL(SNDCTL_DSP_MAPINBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc)))
|
||||||
IOCTL(SNDCTL_DSP_MAPOUTBUF, IOC_R, MK_PTR(TYPE_INT))
|
IOCTL(SNDCTL_DSP_MAPOUTBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc)))
|
||||||
IOCTL(SNDCTL_DSP_NONBLOCK, 0, TYPE_NULL)
|
IOCTL(SNDCTL_DSP_NONBLOCK, 0, TYPE_NULL)
|
||||||
IOCTL(SNDCTL_DSP_POST, 0, TYPE_NULL)
|
IOCTL(SNDCTL_DSP_POST, 0, TYPE_NULL)
|
||||||
IOCTL(SNDCTL_DSP_RESET, 0, TYPE_NULL)
|
IOCTL(SNDCTL_DSP_RESET, 0, TYPE_NULL)
|
||||||
|
|
|
@ -822,8 +822,7 @@ void cpu_loop(CPUARMState *env)
|
||||||
} else if (n == ARM_NR_semihosting
|
} else if (n == ARM_NR_semihosting
|
||||||
|| n == ARM_NR_thumb_semihosting) {
|
|| n == ARM_NR_thumb_semihosting) {
|
||||||
env->regs[0] = do_arm_semihosting (env);
|
env->regs[0] = do_arm_semihosting (env);
|
||||||
} else if (n == 0 || n >= ARM_SYSCALL_BASE
|
} else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) {
|
||||||
|| (env->thumb && n == ARM_THUMB_SYSCALL)) {
|
|
||||||
/* linux syscall */
|
/* linux syscall */
|
||||||
if (env->thumb || n == 0) {
|
if (env->thumb || n == 0) {
|
||||||
n = env->regs[7];
|
n = env->regs[7];
|
||||||
|
@ -3516,39 +3515,16 @@ int main(int argc, char **argv, char **envp)
|
||||||
*/
|
*/
|
||||||
guest_base = HOST_PAGE_ALIGN(guest_base);
|
guest_base = HOST_PAGE_ALIGN(guest_base);
|
||||||
|
|
||||||
if (reserved_va) {
|
if (reserved_va || have_guest_base) {
|
||||||
void *p;
|
guest_base = init_guest_space(guest_base, reserved_va, 0,
|
||||||
int flags;
|
have_guest_base);
|
||||||
|
if (guest_base == (unsigned long)-1) {
|
||||||
flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
|
|
||||||
if (have_guest_base) {
|
|
||||||
flags |= MAP_FIXED;
|
|
||||||
}
|
|
||||||
p = mmap((void *)guest_base, reserved_va, PROT_NONE, flags, -1, 0);
|
|
||||||
if (p == MAP_FAILED) {
|
|
||||||
fprintf(stderr, "Unable to reserve guest address space\n");
|
fprintf(stderr, "Unable to reserve guest address space\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
guest_base = (unsigned long)p;
|
|
||||||
/* Make sure the address is properly aligned. */
|
|
||||||
if (guest_base & ~qemu_host_page_mask) {
|
|
||||||
munmap(p, reserved_va);
|
|
||||||
p = mmap((void *)guest_base, reserved_va + qemu_host_page_size,
|
|
||||||
PROT_NONE, flags, -1, 0);
|
|
||||||
if (p == MAP_FAILED) {
|
|
||||||
fprintf(stderr, "Unable to reserve guest address space\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
guest_base = HOST_PAGE_ALIGN((unsigned long)p);
|
|
||||||
}
|
|
||||||
qemu_log("Reserved 0x%lx bytes of guest address space\n", reserved_va);
|
|
||||||
mmap_next_start = reserved_va;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reserved_va || have_guest_base) {
|
if (reserved_va) {
|
||||||
if (!guest_validate_base(guest_base)) {
|
mmap_next_start = reserved_va;
|
||||||
fprintf(stderr, "Guest base/Reserved VA rejected by guest code\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_USE_GUEST_BASE */
|
#endif /* CONFIG_USE_GUEST_BASE */
|
||||||
|
|
|
@ -204,11 +204,18 @@ int get_osversion(void);
|
||||||
void fork_start(void);
|
void fork_start(void);
|
||||||
void fork_end(int child);
|
void fork_end(int child);
|
||||||
|
|
||||||
/* Return true if the proposed guest_base is suitable for the guest.
|
/* Creates the initial guest address space in the host memory space using
|
||||||
* The guest code may leave a page mapped and populate it if the
|
* the given host start address hint and size. The guest_start parameter
|
||||||
* address is suitable.
|
* specifies the start address of the guest space. guest_base will be the
|
||||||
|
* difference between the host start address computed by this function and
|
||||||
|
* guest_start. If fixed is specified, then the mapped address space must
|
||||||
|
* start at host_start. The real start address of the mapped memory space is
|
||||||
|
* returned or -1 if there was an error.
|
||||||
*/
|
*/
|
||||||
bool guest_validate_base(unsigned long guest_base);
|
unsigned long init_guest_space(unsigned long host_start,
|
||||||
|
unsigned long host_size,
|
||||||
|
unsigned long guest_start,
|
||||||
|
bool fixed);
|
||||||
|
|
||||||
#include "qemu-log.h"
|
#include "qemu-log.h"
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <linux/wireless.h>
|
#include <linux/wireless.h>
|
||||||
|
#include <linux/icmp.h>
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#ifdef TARGET_GPROF
|
#ifdef TARGET_GPROF
|
||||||
#include <sys/gmon.h>
|
#include <sys/gmon.h>
|
||||||
|
@ -1268,7 +1269,6 @@ static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ??? Should this also swap msgh->name? */
|
|
||||||
static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
|
static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
|
||||||
struct target_msghdr *target_msgh)
|
struct target_msghdr *target_msgh)
|
||||||
{
|
{
|
||||||
|
@ -1325,7 +1325,6 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ??? Should this also swap msgh->name? */
|
|
||||||
static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
|
static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
|
||||||
struct msghdr *msgh)
|
struct msghdr *msgh)
|
||||||
{
|
{
|
||||||
|
@ -1360,16 +1359,28 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
|
||||||
target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
|
target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
|
||||||
target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(len));
|
target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(len));
|
||||||
|
|
||||||
if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
|
if ((cmsg->cmsg_level == TARGET_SOL_SOCKET) &&
|
||||||
gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
|
(cmsg->cmsg_type == SCM_RIGHTS)) {
|
||||||
memcpy(target_data, data, len);
|
|
||||||
} else {
|
|
||||||
int *fd = (int *)data;
|
int *fd = (int *)data;
|
||||||
int *target_fd = (int *)target_data;
|
int *target_fd = (int *)target_data;
|
||||||
int i, numfds = len / sizeof(int);
|
int i, numfds = len / sizeof(int);
|
||||||
|
|
||||||
for (i = 0; i < numfds; i++)
|
for (i = 0; i < numfds; i++)
|
||||||
target_fd[i] = tswap32(fd[i]);
|
target_fd[i] = tswap32(fd[i]);
|
||||||
|
} else if ((cmsg->cmsg_level == TARGET_SOL_SOCKET) &&
|
||||||
|
(cmsg->cmsg_type == SO_TIMESTAMP) &&
|
||||||
|
(len == sizeof(struct timeval))) {
|
||||||
|
/* copy struct timeval to target */
|
||||||
|
struct timeval *tv = (struct timeval *)data;
|
||||||
|
struct target_timeval *target_tv =
|
||||||
|
(struct target_timeval *)target_data;
|
||||||
|
|
||||||
|
target_tv->tv_sec = tswapal(tv->tv_sec);
|
||||||
|
target_tv->tv_usec = tswapal(tv->tv_usec);
|
||||||
|
} else {
|
||||||
|
gemu_log("Unsupported ancillary data: %d/%d\n",
|
||||||
|
cmsg->cmsg_level, cmsg->cmsg_type);
|
||||||
|
memcpy(target_data, data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
cmsg = CMSG_NXTHDR(msgh, cmsg);
|
cmsg = CMSG_NXTHDR(msgh, cmsg);
|
||||||
|
@ -1450,6 +1461,25 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
|
||||||
unlock_user (ip_mreq_source, optval_addr, 0);
|
unlock_user (ip_mreq_source, optval_addr, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
goto unimplemented;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SOL_RAW:
|
||||||
|
switch (optname) {
|
||||||
|
case ICMP_FILTER:
|
||||||
|
/* struct icmp_filter takes an u32 value */
|
||||||
|
if (optlen < sizeof(uint32_t)) {
|
||||||
|
return -TARGET_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_user_u32(val, optval_addr)) {
|
||||||
|
return -TARGET_EFAULT;
|
||||||
|
}
|
||||||
|
ret = get_errno(setsockopt(sockfd, level, optname,
|
||||||
|
&val, sizeof(val)));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
goto unimplemented;
|
goto unimplemented;
|
||||||
}
|
}
|
||||||
|
@ -1885,10 +1915,22 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
|
||||||
if (!is_error(ret)) {
|
if (!is_error(ret)) {
|
||||||
len = ret;
|
len = ret;
|
||||||
ret = host_to_target_cmsg(msgp, &msg);
|
ret = host_to_target_cmsg(msgp, &msg);
|
||||||
if (!is_error(ret))
|
if (!is_error(ret)) {
|
||||||
|
msgp->msg_namelen = tswap32(msg.msg_namelen);
|
||||||
|
if (msg.msg_name != NULL) {
|
||||||
|
ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
|
||||||
|
msg.msg_name, msg.msg_namelen);
|
||||||
|
if (ret) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = len;
|
ret = len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
unlock_iovec(vec, target_vec, count, !send);
|
unlock_iovec(vec, target_vec, count, !send);
|
||||||
unlock_user_struct(msgp, target_msg, send ? 0 : 1);
|
unlock_user_struct(msgp, target_msg, send ? 0 : 1);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -4606,6 +4648,12 @@ void syscall_init(void)
|
||||||
#undef STRUCT
|
#undef STRUCT
|
||||||
#undef STRUCT_SPECIAL
|
#undef STRUCT_SPECIAL
|
||||||
|
|
||||||
|
/* Build target_to_host_errno_table[] table from
|
||||||
|
* host_to_target_errno_table[]. */
|
||||||
|
for (i = 0; i < ERRNO_TABLE_SIZE; i++) {
|
||||||
|
target_to_host_errno_table[host_to_target_errno_table[i]] = i;
|
||||||
|
}
|
||||||
|
|
||||||
/* we patch the ioctl size if necessary. We rely on the fact that
|
/* we patch the ioctl size if necessary. We rely on the fact that
|
||||||
no ioctl has all the bits at '1' in the size field */
|
no ioctl has all the bits at '1' in the size field */
|
||||||
ie = ioctl_entries;
|
ie = ioctl_entries;
|
||||||
|
@ -4625,11 +4673,6 @@ void syscall_init(void)
|
||||||
(size << TARGET_IOC_SIZESHIFT);
|
(size << TARGET_IOC_SIZESHIFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Build target_to_host_errno_table[] table from
|
|
||||||
* host_to_target_errno_table[]. */
|
|
||||||
for (i=0; i < ERRNO_TABLE_SIZE; i++)
|
|
||||||
target_to_host_errno_table[host_to_target_errno_table[i]] = i;
|
|
||||||
|
|
||||||
/* automatic consistency check if same arch */
|
/* automatic consistency check if same arch */
|
||||||
#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
|
#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
|
||||||
(defined(__x86_64__) && defined(TARGET_X86_64))
|
(defined(__x86_64__) && defined(TARGET_X86_64))
|
||||||
|
|
|
@ -880,8 +880,8 @@ struct target_pollfd {
|
||||||
#define TARGET_BLKSECTGET TARGET_IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
|
#define TARGET_BLKSECTGET TARGET_IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
|
||||||
#define TARGET_BLKSSZGET TARGET_IO(0x12,104)/* get block device sector size */
|
#define TARGET_BLKSSZGET TARGET_IO(0x12,104)/* get block device sector size */
|
||||||
/* A jump here: 108-111 have been used for various private purposes. */
|
/* A jump here: 108-111 have been used for various private purposes. */
|
||||||
#define TARGET_BLKBSZGET TARGET_IOR(0x12,112,int)
|
#define TARGET_BLKBSZGET TARGET_IOR(0x12, 112, abi_ulong)
|
||||||
#define TARGET_BLKBSZSET TARGET_IOW(0x12,113,int)
|
#define TARGET_BLKBSZSET TARGET_IOW(0x12, 113, abi_ulong)
|
||||||
#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,abi_ulong)
|
#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,abi_ulong)
|
||||||
/* return device size in bytes
|
/* return device size in bytes
|
||||||
(u64 *arg) */
|
(u64 *arg) */
|
||||||
|
@ -2226,8 +2226,8 @@ struct target_eabi_flock64 {
|
||||||
#define TARGET_SNDCTL_DSP_GETTRIGGER TARGET_IOR('P',16, int)
|
#define TARGET_SNDCTL_DSP_GETTRIGGER TARGET_IOR('P',16, int)
|
||||||
#define TARGET_SNDCTL_DSP_GETIPTR TARGET_IORU('P',17)
|
#define TARGET_SNDCTL_DSP_GETIPTR TARGET_IORU('P',17)
|
||||||
#define TARGET_SNDCTL_DSP_GETOPTR TARGET_IORU('P',18)
|
#define TARGET_SNDCTL_DSP_GETOPTR TARGET_IORU('P',18)
|
||||||
#define TARGET_SNDCTL_DSP_MAPINBUF 0x80085013
|
#define TARGET_SNDCTL_DSP_MAPINBUF TARGET_IORU('P', 19)
|
||||||
#define TARGET_SNDCTL_DSP_MAPOUTBUF 0x80085014
|
#define TARGET_SNDCTL_DSP_MAPOUTBUF TARGET_IORU('P', 20)
|
||||||
#define TARGET_SNDCTL_DSP_NONBLOCK 0x0000500e
|
#define TARGET_SNDCTL_DSP_NONBLOCK 0x0000500e
|
||||||
#define TARGET_SNDCTL_DSP_SAMPLESIZE 0xc0045005
|
#define TARGET_SNDCTL_DSP_SAMPLESIZE 0xc0045005
|
||||||
#define TARGET_SNDCTL_DSP_SETDUPLEX 0x00005016
|
#define TARGET_SNDCTL_DSP_SETDUPLEX 0x00005016
|
||||||
|
|
|
@ -77,6 +77,9 @@ STRUCT(audio_buf_info,
|
||||||
STRUCT(count_info,
|
STRUCT(count_info,
|
||||||
TYPE_INT, TYPE_INT, TYPE_INT)
|
TYPE_INT, TYPE_INT, TYPE_INT)
|
||||||
|
|
||||||
|
STRUCT(buffmem_desc,
|
||||||
|
TYPE_PTRVOID, TYPE_INT)
|
||||||
|
|
||||||
STRUCT(mixer_info,
|
STRUCT(mixer_info,
|
||||||
MK_ARRAY(TYPE_CHAR, 16), MK_ARRAY(TYPE_CHAR, 32), TYPE_INT, MK_ARRAY(TYPE_INT, 10))
|
MK_ARRAY(TYPE_CHAR, 16), MK_ARRAY(TYPE_CHAR, 32), TYPE_INT, MK_ARRAY(TYPE_INT, 10))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue