Add /proc/hardware and /proc/cpuinfo,
update SIOCXXX ioctls, fix shmat emulation, add nanoseconds in stat, init field fp_abi on mips -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJc59R0AAoJEPMMOL0/L748px4QAJBgq468iQPge+6L2uwj4bX1 xfclzs/HwNSZaxMj98HGHw+mMdMCZhcRMjZKBcF3bqMQ8vJEHEcHpZBVqGTxoQG9 yDmMZzOSMPGOMjfYasKYaOLNXFexFigVI1tp1EHjuS/PEpaR/O3heFtp4ZqwBA/Y xIXbMVVod0my0uIBbs947CjPHFdFR7UrOvqQIUv0ptCukUsA1NNco4LxvYSur3Co YJgxXct9HIwueubwZKYVCxUI4SfDKuLD2aqkJGolhBSxiHMktzwR3kLdcosU0tnr b9ekBT6UdSVJZirLTHQOOAnU4Ph+bDrLZP3K+WaUdMndLIxWfgV6yaP0Fc5Sdmnv /NDctRthodYqqYXEUtSZrOAkQzVJsUoh6WHg8DKkNS22Q6Hzp6UkiAiKuKvhI/Hs V+5T3Wlkek8M6Zm3Hic7dCz9bATuaMrAb4j/2MI1VKbE1a2OCWruk+v7rAeMhi8d DOS94LJMmLHPUYviXoPyveEA60qm8jRIQAN2Yxuw3CLklDNmxY2UHY5bsfhKfkp5 xTCyJalqUkYIMoj5j6Rtxjfo4SCg4lGyiu5/wKgD5Ry3YLr5NkTLsasutsqbvOt+ D2JIJWny2JvCXMCkJLqffmlm96xglaPfsonrGlhufonuqw2nYyebddQLFo4rIz5b AYxBlo1cb5B77zpGFXC2 =IEm6 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-4.1-pull-request' into staging Add /proc/hardware and /proc/cpuinfo, update SIOCXXX ioctls, fix shmat emulation, add nanoseconds in stat, init field fp_abi on mips # gpg: Signature made Fri 24 May 2019 12:24:36 BST # gpg: using RSA key F30C38BD3F2FBE3C # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full] # gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full] # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full] # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier2/tags/linux-user-for-4.1-pull-request: linux-user: Pass through nanosecond timestamp components for stat syscalls linux-user: Align mmap_find_vma to host page size linux-user: Fix shmat emulation by honoring host SHMLBA linux-user: Sanitize interp_info and, for mips only, init field fp_abi linux-user: Add support for SIOC<G|S>IFPFLAGS ioctls for all targets linux-user: Add support for SIOCSPGRP ioctl for all targets linux-user: Fix support for SIOCATMARK and SIOCGPGRP ioctls for xtensa linux-user: add pseudo /proc/hardware for m68k linux-user: add pseudo /proc/cpuinfo for sparc Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
a7b21f6762
|
@ -3,6 +3,7 @@
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
#include <sys/shm.h>
|
||||||
|
|
||||||
#include "qemu.h"
|
#include "qemu.h"
|
||||||
#include "disas/disas.h"
|
#include "disas/disas.h"
|
||||||
|
@ -2010,6 +2011,8 @@ unsigned long init_guest_space(unsigned long host_start,
|
||||||
unsigned long guest_start,
|
unsigned long guest_start,
|
||||||
bool fixed)
|
bool fixed)
|
||||||
{
|
{
|
||||||
|
/* In order to use host shmat, we must be able to honor SHMLBA. */
|
||||||
|
unsigned long align = MAX(SHMLBA, qemu_host_page_size);
|
||||||
unsigned long current_start, aligned_start;
|
unsigned long current_start, aligned_start;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
|
@ -2027,7 +2030,7 @@ unsigned long init_guest_space(unsigned long host_start,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup the initial flags and start address. */
|
/* Setup the initial flags and start address. */
|
||||||
current_start = host_start & qemu_host_page_mask;
|
current_start = host_start & -align;
|
||||||
flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
|
flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
|
||||||
if (fixed) {
|
if (fixed) {
|
||||||
flags |= MAP_FIXED;
|
flags |= MAP_FIXED;
|
||||||
|
@ -2063,8 +2066,8 @@ unsigned long init_guest_space(unsigned long host_start,
|
||||||
return (unsigned long)-1;
|
return (unsigned long)-1;
|
||||||
}
|
}
|
||||||
munmap((void *)real_start, host_full_size);
|
munmap((void *)real_start, host_full_size);
|
||||||
if (real_start & ~qemu_host_page_mask) {
|
if (real_start & (align - 1)) {
|
||||||
/* The same thing again, but with an extra qemu_host_page_size
|
/* The same thing again, but with extra
|
||||||
* so that we can shift around alignment.
|
* so that we can shift around alignment.
|
||||||
*/
|
*/
|
||||||
unsigned long real_size = host_full_size + qemu_host_page_size;
|
unsigned long real_size = host_full_size + qemu_host_page_size;
|
||||||
|
@ -2077,7 +2080,7 @@ unsigned long init_guest_space(unsigned long host_start,
|
||||||
return (unsigned long)-1;
|
return (unsigned long)-1;
|
||||||
}
|
}
|
||||||
munmap((void *)real_start, real_size);
|
munmap((void *)real_start, real_size);
|
||||||
real_start = HOST_PAGE_ALIGN(real_start);
|
real_start = ROUND_UP(real_start, align);
|
||||||
}
|
}
|
||||||
current_start = real_start;
|
current_start = real_start;
|
||||||
}
|
}
|
||||||
|
@ -2104,7 +2107,7 @@ unsigned long init_guest_space(unsigned long host_start,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ensure the address is properly aligned. */
|
/* Ensure the address is properly aligned. */
|
||||||
if (real_start & ~qemu_host_page_mask) {
|
if (real_start & (align - 1)) {
|
||||||
/* Ideally, we adjust like
|
/* Ideally, we adjust like
|
||||||
*
|
*
|
||||||
* pages: [ ][ ][ ][ ][ ]
|
* pages: [ ][ ][ ][ ][ ]
|
||||||
|
@ -2132,7 +2135,7 @@ unsigned long init_guest_space(unsigned long host_start,
|
||||||
if (real_start == (unsigned long)-1) {
|
if (real_start == (unsigned long)-1) {
|
||||||
return (unsigned long)-1;
|
return (unsigned long)-1;
|
||||||
}
|
}
|
||||||
aligned_start = HOST_PAGE_ALIGN(real_start);
|
aligned_start = ROUND_UP(real_start, align);
|
||||||
} else {
|
} else {
|
||||||
aligned_start = real_start;
|
aligned_start = real_start;
|
||||||
}
|
}
|
||||||
|
@ -2169,7 +2172,7 @@ unsigned long init_guest_space(unsigned long host_start,
|
||||||
* because of trouble with ARM commpage setup.
|
* because of trouble with ARM commpage setup.
|
||||||
*/
|
*/
|
||||||
munmap((void *)real_start, real_size);
|
munmap((void *)real_start, real_size);
|
||||||
current_start += qemu_host_page_size;
|
current_start += align;
|
||||||
if (host_start == current_start) {
|
if (host_start == current_start) {
|
||||||
/* Theoretically possible if host doesn't have any suitably
|
/* Theoretically possible if host doesn't have any suitably
|
||||||
* aligned areas. Normally the first mmap will fail.
|
* aligned areas. Normally the first mmap will fail.
|
||||||
|
@ -2704,6 +2707,11 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
|
||||||
char *elf_interpreter = NULL;
|
char *elf_interpreter = NULL;
|
||||||
char *scratch;
|
char *scratch;
|
||||||
|
|
||||||
|
memset(&interp_info, 0, sizeof(interp_info));
|
||||||
|
#ifdef TARGET_MIPS
|
||||||
|
interp_info.fp_abi = MIPS_ABI_FP_UNKNOWN;
|
||||||
|
#endif
|
||||||
|
|
||||||
info->start_mmap = (abi_ulong)ELF_START_MMAP;
|
info->start_mmap = (abi_ulong)ELF_START_MMAP;
|
||||||
|
|
||||||
load_elf_image(bprm->filename, bprm->fd, info,
|
load_elf_image(bprm->filename, bprm->fd, info,
|
||||||
|
|
|
@ -206,6 +206,8 @@
|
||||||
IOCTL(SIOCADDMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
IOCTL(SIOCADDMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||||
IOCTL(SIOCDELMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
IOCTL(SIOCDELMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
|
||||||
IOCTL(SIOCGIFINDEX, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
|
IOCTL(SIOCGIFINDEX, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
|
||||||
|
IOCTL(SIOCSIFPFLAGS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
|
||||||
|
IOCTL(SIOCGIFPFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
|
||||||
IOCTL(SIOCSIFLINK, 0, TYPE_NULL)
|
IOCTL(SIOCSIFLINK, 0, TYPE_NULL)
|
||||||
IOCTL_SPECIAL(SIOCGIFCONF, IOC_W | IOC_R, do_ioctl_ifconf,
|
IOCTL_SPECIAL(SIOCGIFCONF, IOC_W | IOC_R, do_ioctl_ifconf,
|
||||||
MK_PTR(MK_STRUCT(STRUCT_ifconf)))
|
MK_PTR(MK_STRUCT(STRUCT_ifconf)))
|
||||||
|
@ -218,6 +220,7 @@
|
||||||
IOCTL(SIOCSRARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
|
IOCTL(SIOCSRARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
|
||||||
IOCTL(SIOCGRARP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
|
IOCTL(SIOCGRARP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
|
||||||
IOCTL(SIOCGIWNAME, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_char_ifreq)))
|
IOCTL(SIOCGIWNAME, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_char_ifreq)))
|
||||||
|
IOCTL(SIOCSPGRP, IOC_W, MK_PTR(TYPE_INT)) /* pid_t */
|
||||||
IOCTL(SIOCGPGRP, IOC_R, MK_PTR(TYPE_INT)) /* pid_t */
|
IOCTL(SIOCGPGRP, IOC_R, MK_PTR(TYPE_INT)) /* pid_t */
|
||||||
IOCTL(SIOCGSTAMP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timeval)))
|
IOCTL(SIOCGSTAMP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timeval)))
|
||||||
IOCTL(SIOCGSTAMPNS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timespec)))
|
IOCTL(SIOCGSTAMPNS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timespec)))
|
||||||
|
|
|
@ -202,49 +202,52 @@ unsigned long last_brk;
|
||||||
|
|
||||||
/* Subroutine of mmap_find_vma, used when we have pre-allocated a chunk
|
/* Subroutine of mmap_find_vma, used when we have pre-allocated a chunk
|
||||||
of guest address space. */
|
of guest address space. */
|
||||||
static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size)
|
static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size,
|
||||||
|
abi_ulong align)
|
||||||
{
|
{
|
||||||
abi_ulong addr;
|
abi_ulong addr, end_addr, incr = qemu_host_page_size;
|
||||||
abi_ulong end_addr;
|
|
||||||
int prot;
|
int prot;
|
||||||
int looped = 0;
|
bool looped = false;
|
||||||
|
|
||||||
if (size > reserved_va) {
|
if (size > reserved_va) {
|
||||||
return (abi_ulong)-1;
|
return (abi_ulong)-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = HOST_PAGE_ALIGN(size);
|
/* Note that start and size have already been aligned by mmap_find_vma. */
|
||||||
end_addr = start + size;
|
|
||||||
if (end_addr > reserved_va) {
|
|
||||||
end_addr = reserved_va;
|
|
||||||
}
|
|
||||||
addr = end_addr - qemu_host_page_size;
|
|
||||||
|
|
||||||
|
end_addr = start + size;
|
||||||
|
if (start > reserved_va - size) {
|
||||||
|
/* Start at the top of the address space. */
|
||||||
|
end_addr = ((reserved_va - size) & -align) + size;
|
||||||
|
looped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Search downward from END_ADDR, checking to see if a page is in use. */
|
||||||
|
addr = end_addr;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
addr -= incr;
|
||||||
if (addr > end_addr) {
|
if (addr > end_addr) {
|
||||||
if (looped) {
|
if (looped) {
|
||||||
|
/* Failure. The entire address space has been searched. */
|
||||||
return (abi_ulong)-1;
|
return (abi_ulong)-1;
|
||||||
}
|
}
|
||||||
end_addr = reserved_va;
|
/* Re-start at the top of the address space. */
|
||||||
addr = end_addr - qemu_host_page_size;
|
addr = end_addr = ((reserved_va - size) & -align) + size;
|
||||||
looped = 1;
|
looped = true;
|
||||||
continue;
|
} else {
|
||||||
|
prot = page_get_flags(addr);
|
||||||
|
if (prot) {
|
||||||
|
/* Page in use. Restart below this page. */
|
||||||
|
addr = end_addr = ((addr - size) & -align) + size;
|
||||||
|
} else if (addr && addr + size == end_addr) {
|
||||||
|
/* Success! All pages between ADDR and END_ADDR are free. */
|
||||||
|
if (start == mmap_next_start) {
|
||||||
|
mmap_next_start = addr;
|
||||||
|
}
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
prot = page_get_flags(addr);
|
|
||||||
if (prot) {
|
|
||||||
end_addr = addr;
|
|
||||||
}
|
|
||||||
if (addr && addr + size == end_addr) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
addr -= qemu_host_page_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (start == mmap_next_start) {
|
|
||||||
mmap_next_start = addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -253,23 +256,26 @@ static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size)
|
||||||
* It must be called with mmap_lock() held.
|
* It must be called with mmap_lock() held.
|
||||||
* Return -1 if error.
|
* Return -1 if error.
|
||||||
*/
|
*/
|
||||||
abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
|
abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong align)
|
||||||
{
|
{
|
||||||
void *ptr, *prev;
|
void *ptr, *prev;
|
||||||
abi_ulong addr;
|
abi_ulong addr;
|
||||||
int wrapped, repeat;
|
int wrapped, repeat;
|
||||||
|
|
||||||
|
align = MAX(align, qemu_host_page_size);
|
||||||
|
|
||||||
/* If 'start' == 0, then a default start address is used. */
|
/* If 'start' == 0, then a default start address is used. */
|
||||||
if (start == 0) {
|
if (start == 0) {
|
||||||
start = mmap_next_start;
|
start = mmap_next_start;
|
||||||
} else {
|
} else {
|
||||||
start &= qemu_host_page_mask;
|
start &= qemu_host_page_mask;
|
||||||
}
|
}
|
||||||
|
start = ROUND_UP(start, align);
|
||||||
|
|
||||||
size = HOST_PAGE_ALIGN(size);
|
size = HOST_PAGE_ALIGN(size);
|
||||||
|
|
||||||
if (reserved_va) {
|
if (reserved_va) {
|
||||||
return mmap_find_vma_reserved(start, size);
|
return mmap_find_vma_reserved(start, size, align);
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = start;
|
addr = start;
|
||||||
|
@ -299,7 +305,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
|
||||||
if (h2g_valid(ptr + size - 1)) {
|
if (h2g_valid(ptr + size - 1)) {
|
||||||
addr = h2g(ptr);
|
addr = h2g(ptr);
|
||||||
|
|
||||||
if ((addr & ~TARGET_PAGE_MASK) == 0) {
|
if ((addr & (align - 1)) == 0) {
|
||||||
/* Success. */
|
/* Success. */
|
||||||
if (start == mmap_next_start && addr >= TASK_UNMAPPED_BASE) {
|
if (start == mmap_next_start && addr >= TASK_UNMAPPED_BASE) {
|
||||||
mmap_next_start = addr + size;
|
mmap_next_start = addr + size;
|
||||||
|
@ -313,12 +319,12 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
|
||||||
/* Assume the result that the kernel gave us is the
|
/* Assume the result that the kernel gave us is the
|
||||||
first with enough free space, so start again at the
|
first with enough free space, so start again at the
|
||||||
next higher target page. */
|
next higher target page. */
|
||||||
addr = TARGET_PAGE_ALIGN(addr);
|
addr = ROUND_UP(addr, align);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
/* Sometimes the kernel decides to perform the allocation
|
/* Sometimes the kernel decides to perform the allocation
|
||||||
at the top end of memory instead. */
|
at the top end of memory instead. */
|
||||||
addr &= TARGET_PAGE_MASK;
|
addr &= -align;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
/* Start over at low memory. */
|
/* Start over at low memory. */
|
||||||
|
@ -416,7 +422,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||||
if (!(flags & MAP_FIXED)) {
|
if (!(flags & MAP_FIXED)) {
|
||||||
host_len = len + offset - host_offset;
|
host_len = len + offset - host_offset;
|
||||||
host_len = HOST_PAGE_ALIGN(host_len);
|
host_len = HOST_PAGE_ALIGN(host_len);
|
||||||
start = mmap_find_vma(real_start, host_len);
|
start = mmap_find_vma(real_start, host_len, TARGET_PAGE_SIZE);
|
||||||
if (start == (abi_ulong)-1) {
|
if (start == (abi_ulong)-1) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -710,7 +716,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
|
||||||
} else if (flags & MREMAP_MAYMOVE) {
|
} else if (flags & MREMAP_MAYMOVE) {
|
||||||
abi_ulong mmap_start;
|
abi_ulong mmap_start;
|
||||||
|
|
||||||
mmap_start = mmap_find_vma(0, new_size);
|
mmap_start = mmap_find_vma(0, new_size, TARGET_PAGE_SIZE);
|
||||||
|
|
||||||
if (mmap_start == -1) {
|
if (mmap_start == -1) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
|
|
|
@ -443,7 +443,7 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
|
||||||
abi_ulong new_addr);
|
abi_ulong new_addr);
|
||||||
extern unsigned long last_brk;
|
extern unsigned long last_brk;
|
||||||
extern abi_ulong mmap_next_start;
|
extern abi_ulong mmap_next_start;
|
||||||
abi_ulong mmap_find_vma(abi_ulong, abi_ulong);
|
abi_ulong mmap_find_vma(abi_ulong, abi_ulong, abi_ulong);
|
||||||
void mmap_fork_start(void);
|
void mmap_fork_start(void);
|
||||||
void mmap_fork_end(int child);
|
void mmap_fork_end(int child);
|
||||||
|
|
||||||
|
|
|
@ -3914,7 +3914,8 @@ static inline abi_ulong do_shmat(CPUArchState *cpu_env,
|
||||||
else {
|
else {
|
||||||
abi_ulong mmap_start;
|
abi_ulong mmap_start;
|
||||||
|
|
||||||
mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
|
/* In order to use the host shmat, we need to honor host SHMLBA. */
|
||||||
|
mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
|
||||||
|
|
||||||
if (mmap_start == -1) {
|
if (mmap_start == -1) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
|
@ -6412,6 +6413,11 @@ static inline abi_long host_to_target_stat64(void *cpu_env,
|
||||||
__put_user(host_st->st_atime, &target_st->target_st_atime);
|
__put_user(host_st->st_atime, &target_st->target_st_atime);
|
||||||
__put_user(host_st->st_mtime, &target_st->target_st_mtime);
|
__put_user(host_st->st_mtime, &target_st->target_st_mtime);
|
||||||
__put_user(host_st->st_ctime, &target_st->target_st_ctime);
|
__put_user(host_st->st_ctime, &target_st->target_st_ctime);
|
||||||
|
#if _POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700
|
||||||
|
__put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
|
||||||
|
__put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
|
||||||
|
__put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
|
||||||
|
#endif
|
||||||
unlock_user_struct(target_st, target_addr, 1);
|
unlock_user_struct(target_st, target_addr, 1);
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
|
@ -6442,6 +6448,11 @@ static inline abi_long host_to_target_stat64(void *cpu_env,
|
||||||
__put_user(host_st->st_atime, &target_st->target_st_atime);
|
__put_user(host_st->st_atime, &target_st->target_st_atime);
|
||||||
__put_user(host_st->st_mtime, &target_st->target_st_mtime);
|
__put_user(host_st->st_mtime, &target_st->target_st_mtime);
|
||||||
__put_user(host_st->st_ctime, &target_st->target_st_ctime);
|
__put_user(host_st->st_ctime, &target_st->target_st_ctime);
|
||||||
|
#if _POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700
|
||||||
|
__put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
|
||||||
|
__put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
|
||||||
|
__put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
|
||||||
|
#endif
|
||||||
unlock_user_struct(target_st, target_addr, 1);
|
unlock_user_struct(target_st, target_addr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6790,12 +6801,15 @@ static int is_proc_myself(const char *filename, const char *entry)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) || \
|
||||||
|
defined(TARGET_SPARC) || defined(TARGET_M68K)
|
||||||
static int is_proc(const char *filename, const char *entry)
|
static int is_proc(const char *filename, const char *entry)
|
||||||
{
|
{
|
||||||
return strcmp(filename, entry) == 0;
|
return strcmp(filename, entry) == 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
||||||
static int open_net_route(void *cpu_env, int fd)
|
static int open_net_route(void *cpu_env, int fd)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
@ -6840,6 +6854,22 @@ static int open_net_route(void *cpu_env, int fd)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(TARGET_SPARC)
|
||||||
|
static int open_cpuinfo(void *cpu_env, int fd)
|
||||||
|
{
|
||||||
|
dprintf(fd, "type\t\t: sun4u\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(TARGET_M68K)
|
||||||
|
static int open_hardware(void *cpu_env, int fd)
|
||||||
|
{
|
||||||
|
dprintf(fd, "Model:\t\tqemu-m68k\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
|
static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
|
||||||
{
|
{
|
||||||
struct fake_open {
|
struct fake_open {
|
||||||
|
@ -6855,6 +6885,12 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags,
|
||||||
{ "cmdline", open_self_cmdline, is_proc_myself },
|
{ "cmdline", open_self_cmdline, is_proc_myself },
|
||||||
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
||||||
{ "/proc/net/route", open_net_route, is_proc },
|
{ "/proc/net/route", open_net_route, is_proc },
|
||||||
|
#endif
|
||||||
|
#if defined(TARGET_SPARC)
|
||||||
|
{ "/proc/cpuinfo", open_cpuinfo, is_proc },
|
||||||
|
#endif
|
||||||
|
#if defined(TARGET_M68K)
|
||||||
|
{ "/proc/hardware", open_hardware, is_proc },
|
||||||
#endif
|
#endif
|
||||||
{ NULL, NULL, NULL }
|
{ NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
@ -8870,6 +8906,15 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||||
__put_user(st.st_atime, &target_st->target_st_atime);
|
__put_user(st.st_atime, &target_st->target_st_atime);
|
||||||
__put_user(st.st_mtime, &target_st->target_st_mtime);
|
__put_user(st.st_mtime, &target_st->target_st_mtime);
|
||||||
__put_user(st.st_ctime, &target_st->target_st_ctime);
|
__put_user(st.st_ctime, &target_st->target_st_ctime);
|
||||||
|
#if (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) && \
|
||||||
|
defined(TARGET_STAT_HAVE_NSEC)
|
||||||
|
__put_user(st.st_atim.tv_nsec,
|
||||||
|
&target_st->target_st_atime_nsec);
|
||||||
|
__put_user(st.st_mtim.tv_nsec,
|
||||||
|
&target_st->target_st_mtime_nsec);
|
||||||
|
__put_user(st.st_ctim.tv_nsec,
|
||||||
|
&target_st->target_st_ctime_nsec);
|
||||||
|
#endif
|
||||||
unlock_user_struct(target_st, arg2, 1);
|
unlock_user_struct(target_st, arg2, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -737,13 +737,17 @@ struct target_pollfd {
|
||||||
#define TARGET_KDSETLED 0x4B32 /* set led state [lights, not flags] */
|
#define TARGET_KDSETLED 0x4B32 /* set led state [lights, not flags] */
|
||||||
#define TARGET_KDSIGACCEPT 0x4B4E
|
#define TARGET_KDSIGACCEPT 0x4B4E
|
||||||
|
|
||||||
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SH4)
|
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SH4) || \
|
||||||
|
defined(TARGET_XTENSA)
|
||||||
#define TARGET_SIOCATMARK TARGET_IOR('s', 7, int)
|
#define TARGET_SIOCATMARK TARGET_IOR('s', 7, int)
|
||||||
|
#define TARGET_SIOCSPGRP TARGET_IOW('s', 8, pid_t)
|
||||||
#define TARGET_SIOCGPGRP TARGET_IOR('s', 9, pid_t)
|
#define TARGET_SIOCGPGRP TARGET_IOR('s', 9, pid_t)
|
||||||
#else
|
#else
|
||||||
#define TARGET_SIOCATMARK 0x8905
|
#define TARGET_SIOCATMARK 0x8905
|
||||||
|
#define TARGET_SIOCSPGRP 0x8902
|
||||||
#define TARGET_SIOCGPGRP 0x8904
|
#define TARGET_SIOCGPGRP 0x8904
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TARGET_SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
|
#define TARGET_SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
|
||||||
#define TARGET_SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
|
#define TARGET_SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
|
||||||
|
|
||||||
|
@ -778,6 +782,8 @@ struct target_pollfd {
|
||||||
#define TARGET_SIOCADDMULTI 0x8931 /* Multicast address lists */
|
#define TARGET_SIOCADDMULTI 0x8931 /* Multicast address lists */
|
||||||
#define TARGET_SIOCDELMULTI 0x8932
|
#define TARGET_SIOCDELMULTI 0x8932
|
||||||
#define TARGET_SIOCGIFINDEX 0x8933
|
#define TARGET_SIOCGIFINDEX 0x8933
|
||||||
|
#define TARGET_SIOCSIFPFLAGS 0x8934 /* set extended flags */
|
||||||
|
#define TARGET_SIOCGIFPFLAGS 0x8935 /* get extended flags */
|
||||||
|
|
||||||
/* Bridging control calls */
|
/* Bridging control calls */
|
||||||
#define TARGET_SIOCGIFBR 0x8940 /* Bridging support */
|
#define TARGET_SIOCGIFBR 0x8940 /* Bridging support */
|
||||||
|
@ -1179,6 +1185,7 @@ struct target_winsize {
|
||||||
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) \
|
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) \
|
||||||
|| (defined(TARGET_ARM) && defined(TARGET_ABI32)) \
|
|| (defined(TARGET_ARM) && defined(TARGET_ABI32)) \
|
||||||
|| defined(TARGET_CRIS)
|
|| defined(TARGET_CRIS)
|
||||||
|
#define TARGET_STAT_HAVE_NSEC
|
||||||
struct target_stat {
|
struct target_stat {
|
||||||
unsigned short st_dev;
|
unsigned short st_dev;
|
||||||
unsigned short __pad1;
|
unsigned short __pad1;
|
||||||
|
@ -1193,11 +1200,11 @@ struct target_stat {
|
||||||
abi_ulong st_blksize;
|
abi_ulong st_blksize;
|
||||||
abi_ulong st_blocks;
|
abi_ulong st_blocks;
|
||||||
abi_ulong target_st_atime;
|
abi_ulong target_st_atime;
|
||||||
abi_ulong __unused1;
|
abi_ulong target_st_atime_nsec;
|
||||||
abi_ulong target_st_mtime;
|
abi_ulong target_st_mtime;
|
||||||
abi_ulong __unused2;
|
abi_ulong target_st_mtime_nsec;
|
||||||
abi_ulong target_st_ctime;
|
abi_ulong target_st_ctime;
|
||||||
abi_ulong __unused3;
|
abi_ulong target_st_ctime_nsec;
|
||||||
abi_ulong __unused4;
|
abi_ulong __unused4;
|
||||||
abi_ulong __unused5;
|
abi_ulong __unused5;
|
||||||
};
|
};
|
||||||
|
@ -1229,13 +1236,13 @@ struct target_stat64 {
|
||||||
abi_ulong __pad4; /* future possible st_blocks high bits */
|
abi_ulong __pad4; /* future possible st_blocks high bits */
|
||||||
|
|
||||||
abi_ulong target_st_atime;
|
abi_ulong target_st_atime;
|
||||||
abi_ulong __pad5;
|
abi_ulong target_st_atime_nsec;
|
||||||
|
|
||||||
abi_ulong target_st_mtime;
|
abi_ulong target_st_mtime;
|
||||||
abi_ulong __pad6;
|
abi_ulong target_st_mtime_nsec;
|
||||||
|
|
||||||
abi_ulong target_st_ctime;
|
abi_ulong target_st_ctime;
|
||||||
abi_ulong __pad7; /* will be high 32 bits of ctime someday */
|
abi_ulong target_st_ctime_nsec;
|
||||||
|
|
||||||
unsigned long long st_ino;
|
unsigned long long st_ino;
|
||||||
} QEMU_PACKED;
|
} QEMU_PACKED;
|
||||||
|
@ -1314,19 +1321,20 @@ struct target_stat64 {
|
||||||
unsigned int st_blocks;
|
unsigned int st_blocks;
|
||||||
|
|
||||||
abi_ulong target_st_atime;
|
abi_ulong target_st_atime;
|
||||||
abi_ulong __unused1;
|
abi_ulong target_st_atime_nsec;
|
||||||
|
|
||||||
abi_ulong target_st_mtime;
|
abi_ulong target_st_mtime;
|
||||||
abi_ulong __unused2;
|
abi_ulong target_st_mtime_nsec;
|
||||||
|
|
||||||
abi_ulong target_st_ctime;
|
abi_ulong target_st_ctime;
|
||||||
abi_ulong __unused3;
|
abi_ulong target_st_ctime_nsec;
|
||||||
|
|
||||||
abi_ulong __unused4[3];
|
abi_ulong __unused4[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined(TARGET_SPARC)
|
#elif defined(TARGET_SPARC)
|
||||||
|
|
||||||
|
#define TARGET_STAT_HAVE_NSEC
|
||||||
struct target_stat {
|
struct target_stat {
|
||||||
unsigned short st_dev;
|
unsigned short st_dev;
|
||||||
abi_ulong st_ino;
|
abi_ulong st_ino;
|
||||||
|
@ -1337,14 +1345,14 @@ struct target_stat {
|
||||||
unsigned short st_rdev;
|
unsigned short st_rdev;
|
||||||
abi_long st_size;
|
abi_long st_size;
|
||||||
abi_long target_st_atime;
|
abi_long target_st_atime;
|
||||||
abi_ulong __unused1;
|
abi_ulong target_st_atime_nsec;
|
||||||
abi_long target_st_mtime;
|
abi_long target_st_mtime;
|
||||||
abi_ulong __unused2;
|
abi_ulong target_st_mtime_nsec;
|
||||||
abi_long target_st_ctime;
|
abi_long target_st_ctime;
|
||||||
abi_ulong __unused3;
|
abi_ulong target_st_ctime_nsec;
|
||||||
abi_long st_blksize;
|
abi_long st_blksize;
|
||||||
abi_long st_blocks;
|
abi_long st_blocks;
|
||||||
abi_ulong __unused4[2];
|
abi_ulong __unused1[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TARGET_HAS_STRUCT_STAT64
|
#define TARGET_HAS_STRUCT_STAT64
|
||||||
|
@ -1372,20 +1380,21 @@ struct target_stat64 {
|
||||||
unsigned int st_blocks;
|
unsigned int st_blocks;
|
||||||
|
|
||||||
unsigned int target_st_atime;
|
unsigned int target_st_atime;
|
||||||
unsigned int __unused1;
|
unsigned int target_st_atime_nsec;
|
||||||
|
|
||||||
unsigned int target_st_mtime;
|
unsigned int target_st_mtime;
|
||||||
unsigned int __unused2;
|
unsigned int target_st_mtime_nsec;
|
||||||
|
|
||||||
unsigned int target_st_ctime;
|
unsigned int target_st_ctime;
|
||||||
unsigned int __unused3;
|
unsigned int target_st_ctime_nsec;
|
||||||
|
|
||||||
unsigned int __unused4;
|
unsigned int __unused1;
|
||||||
unsigned int __unused5;
|
unsigned int __unused2;
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined(TARGET_PPC)
|
#elif defined(TARGET_PPC)
|
||||||
|
|
||||||
|
#define TARGET_STAT_HAVE_NSEC
|
||||||
struct target_stat {
|
struct target_stat {
|
||||||
abi_ulong st_dev;
|
abi_ulong st_dev;
|
||||||
abi_ulong st_ino;
|
abi_ulong st_ino;
|
||||||
|
@ -1443,6 +1452,7 @@ struct QEMU_PACKED target_stat64 {
|
||||||
|
|
||||||
#elif defined(TARGET_MICROBLAZE)
|
#elif defined(TARGET_MICROBLAZE)
|
||||||
|
|
||||||
|
#define TARGET_STAT_HAVE_NSEC
|
||||||
struct target_stat {
|
struct target_stat {
|
||||||
abi_ulong st_dev;
|
abi_ulong st_dev;
|
||||||
abi_ulong st_ino;
|
abi_ulong st_ino;
|
||||||
|
@ -1558,6 +1568,7 @@ struct target_stat64 {
|
||||||
|
|
||||||
#elif defined(TARGET_ABI_MIPSN64)
|
#elif defined(TARGET_ABI_MIPSN64)
|
||||||
|
|
||||||
|
#define TARGET_STAT_HAVE_NSEC
|
||||||
/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */
|
/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */
|
||||||
struct target_stat {
|
struct target_stat {
|
||||||
unsigned int st_dev;
|
unsigned int st_dev;
|
||||||
|
@ -1597,6 +1608,7 @@ struct target_stat {
|
||||||
|
|
||||||
#elif defined(TARGET_ABI_MIPSN32)
|
#elif defined(TARGET_ABI_MIPSN32)
|
||||||
|
|
||||||
|
#define TARGET_STAT_HAVE_NSEC
|
||||||
struct target_stat {
|
struct target_stat {
|
||||||
abi_ulong st_dev;
|
abi_ulong st_dev;
|
||||||
abi_ulong st_pad0[3]; /* Reserved for st_dev expansion */
|
abi_ulong st_pad0[3]; /* Reserved for st_dev expansion */
|
||||||
|
@ -1621,6 +1633,7 @@ struct target_stat {
|
||||||
|
|
||||||
#elif defined(TARGET_ABI_MIPSO32)
|
#elif defined(TARGET_ABI_MIPSO32)
|
||||||
|
|
||||||
|
#define TARGET_STAT_HAVE_NSEC
|
||||||
struct target_stat {
|
struct target_stat {
|
||||||
unsigned st_dev;
|
unsigned st_dev;
|
||||||
abi_long st_pad1[3]; /* Reserved for network id */
|
abi_long st_pad1[3]; /* Reserved for network id */
|
||||||
|
@ -1737,6 +1750,7 @@ struct target_stat64 {
|
||||||
|
|
||||||
#elif defined(TARGET_SH4)
|
#elif defined(TARGET_SH4)
|
||||||
|
|
||||||
|
#define TARGET_STAT_HAVE_NSEC
|
||||||
struct target_stat {
|
struct target_stat {
|
||||||
abi_ulong st_dev;
|
abi_ulong st_dev;
|
||||||
abi_ulong st_ino;
|
abi_ulong st_ino;
|
||||||
|
@ -1796,6 +1810,7 @@ struct QEMU_PACKED target_stat64 {
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined(TARGET_I386) && !defined(TARGET_ABI32)
|
#elif defined(TARGET_I386) && !defined(TARGET_ABI32)
|
||||||
|
#define TARGET_STAT_HAVE_NSEC
|
||||||
struct target_stat {
|
struct target_stat {
|
||||||
abi_ulong st_dev;
|
abi_ulong st_dev;
|
||||||
abi_ulong st_ino;
|
abi_ulong st_ino;
|
||||||
|
@ -1841,6 +1856,7 @@ struct target_stat {
|
||||||
abi_ulong __unused[3];
|
abi_ulong __unused[3];
|
||||||
};
|
};
|
||||||
#elif defined(TARGET_AARCH64)
|
#elif defined(TARGET_AARCH64)
|
||||||
|
#define TARGET_STAT_HAVE_NSEC
|
||||||
struct target_stat {
|
struct target_stat {
|
||||||
abi_ulong st_dev;
|
abi_ulong st_dev;
|
||||||
abi_ulong st_ino;
|
abi_ulong st_ino;
|
||||||
|
@ -1863,6 +1879,7 @@ struct target_stat {
|
||||||
unsigned int __unused[2];
|
unsigned int __unused[2];
|
||||||
};
|
};
|
||||||
#elif defined(TARGET_XTENSA)
|
#elif defined(TARGET_XTENSA)
|
||||||
|
#define TARGET_STAT_HAVE_NSEC
|
||||||
struct target_stat {
|
struct target_stat {
|
||||||
abi_ulong st_dev;
|
abi_ulong st_dev;
|
||||||
abi_ulong st_ino;
|
abi_ulong st_ino;
|
||||||
|
@ -1912,6 +1929,7 @@ struct target_stat64 {
|
||||||
|
|
||||||
/* These are the asm-generic versions of the stat and stat64 structures */
|
/* These are the asm-generic versions of the stat and stat64 structures */
|
||||||
|
|
||||||
|
#define TARGET_STAT_HAVE_NSEC
|
||||||
struct target_stat {
|
struct target_stat {
|
||||||
abi_ulong st_dev;
|
abi_ulong st_dev;
|
||||||
abi_ulong st_ino;
|
abi_ulong st_ino;
|
||||||
|
@ -1963,6 +1981,7 @@ struct target_stat64 {
|
||||||
|
|
||||||
#elif defined(TARGET_HPPA)
|
#elif defined(TARGET_HPPA)
|
||||||
|
|
||||||
|
#define TARGET_STAT_HAVE_NSEC
|
||||||
struct target_stat {
|
struct target_stat {
|
||||||
abi_uint st_dev;
|
abi_uint st_dev;
|
||||||
abi_uint st_ino;
|
abi_uint st_ino;
|
||||||
|
|
Loading…
Reference in New Issue