Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-5.0…
Browse files Browse the repository at this point in the history
…-pull-request' into staging

Fix mmap guest space and brk
Add FS/FD/RTC/KCOV ioctls

# gpg: Signature made Thu 23 Jan 2020 08:21:41 GMT
# gpg:                using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C
# gpg:                issuer "laurent@vivier.eu"
# 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-5.0-pull-request:
  linux-user: Add support for read/clear RTC voltage low detector using ioctls
  linux-user: Add support for getting/setting RTC PLL correction using ioctls
  linux-user: Add support for getting/setting RTC wakeup alarm using ioctls
  linux-user: Add support for getting/setting RTC periodic interrupt and epoch using ioctls
  linux-user: Add support for getting/setting RTC time and alarm using ioctls
  linux-user: Add support for enabling/disabling RTC features using ioctls
  linux-user: Add support for TYPE_LONG and TYPE_ULONG in do_ioctl()
  linux-user: Add support for KCOV_INIT_TRACE ioctl
  linux-user: Add support for KCOV_<ENABLE|DISABLE> ioctls
  configure: Detect kcov support and introduce CONFIG_KCOV
  linux-user: Add support for FDFMT<BEG|TRK|END> ioctls
  linux-user: Add support for FD<SETEMSGTRESH|SETMAXERRS|GETMAXERRS> ioctls
  linux-user: Add support for FS_IOC32_<GET|SET>VERSION ioctls
  linux-user: Add support for FS_IOC32_<GET|SET>FLAGS ioctls
  linux-user: Add support for FS_IOC_<GET|SET>VERSION ioctls
  linux-user: Reserve space for brk
  linux-user:Fix align mistake when mmap guest space

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Jan 23, 2020
2 parents 7cea426 + a7b0974 commit b7c359c
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 21 deletions.
9 changes: 9 additions & 0 deletions configure
Expand Up @@ -4761,6 +4761,12 @@ if compile_prog "" "" ; then
syncfs=yes
fi

# check for kcov support (kernel must be 4.4+, compiled with certain options)
kcov=no
if check_include sys/kcov.h ; then
kcov=yes
fi

# Check we have a new enough version of sphinx-build
has_sphinx_build() {
# This is a bit awkward but works: create a trivial document and
Expand Down Expand Up @@ -6874,6 +6880,9 @@ fi
if test "$syncfs" = "yes" ; then
echo "CONFIG_SYNCFS=y" >> $config_host_mak
fi
if test "$kcov" = "yes" ; then
echo "CONFIG_KCOV=y" >> $config_host_mak
fi
if test "$inotify" = "yes" ; then
echo "CONFIG_INOTIFY=y" >> $config_host_mak
fi
Expand Down
75 changes: 57 additions & 18 deletions linux-user/elfload.c
Expand Up @@ -10,6 +10,7 @@
#include "qemu/path.h"
#include "qemu/queue.h"
#include "qemu/guest-random.h"
#include "qemu/units.h"

#ifdef _ARCH_PPC64
#undef ARCH_DLINFO
Expand Down Expand Up @@ -2191,7 +2192,7 @@ unsigned long init_guest_space(unsigned long host_start,
* to where we need to put the commpage.
*/
munmap((void *)real_start, host_size);
real_size = aligned_size + qemu_host_page_size;
real_size = aligned_size + align;
real_start = (unsigned long)
mmap((void *)real_start, real_size, PROT_NONE, flags, -1, 0);
if (real_start == (unsigned long)-1) {
Expand Down Expand Up @@ -2364,24 +2365,51 @@ static void load_elf_image(const char *image_name, int image_fd,
}
}

load_addr = loaddr;
if (ehdr->e_type == ET_DYN) {
/* The image indicates that it can be loaded anywhere. Find a
location that can hold the memory space required. If the
image is pre-linked, LOADDR will be non-zero. Since we do
not supply MAP_FIXED here we'll use that address if and
only if it remains available. */
load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE,
MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
-1, 0);
if (load_addr == -1) {
goto exit_perror;
if (pinterp_name != NULL) {
/*
* This is the main executable.
*
* Reserve extra space for brk.
* We hold on to this space while placing the interpreter
* and the stack, lest they be placed immediately after
* the data segment and block allocation from the brk.
*
* 16MB is chosen as "large enough" without being so large
* as to allow the result to not fit with a 32-bit guest on
* a 32-bit host.
*/
info->reserve_brk = 16 * MiB;
hiaddr += info->reserve_brk;

if (ehdr->e_type == ET_EXEC) {
/*
* Make sure that the low address does not conflict with
* MMAP_MIN_ADDR or the QEMU application itself.
*/
probe_guest_base(image_name, loaddr, hiaddr);
}
} else if (pinterp_name != NULL) {
/* This is the main executable. Make sure that the low
address does not conflict with MMAP_MIN_ADDR or the
QEMU application itself. */
probe_guest_base(image_name, loaddr, hiaddr);
}

/*
* Reserve address space for all of this.
*
* In the case of ET_EXEC, we supply MAP_FIXED so that we get
* exactly the address range that is required.
*
* Otherwise this is ET_DYN, and we are searching for a location
* that can hold the memory space required. If the image is
* pre-linked, LOADDR will be non-zero, and the kernel should
* honor that address if it happens to be free.
*
* In both cases, we will overwrite pages in this range with mappings
* from the executable.
*/
load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE,
MAP_PRIVATE | MAP_ANON | MAP_NORESERVE |
(ehdr->e_type == ET_EXEC ? MAP_FIXED : 0),
-1, 0);
if (load_addr == -1) {
goto exit_perror;
}
load_bias = load_addr - loaddr;

Expand Down Expand Up @@ -2860,6 +2888,17 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
bprm->core_dump = &elf_core_dump;
#endif

/*
* If we reserved extra space for brk, release it now.
* The implementation of do_brk in syscalls.c expects to be able
* to mmap pages in this space.
*/
if (info->reserve_brk) {
abi_ulong start_brk = HOST_PAGE_ALIGN(info->brk);
abi_ulong end_brk = HOST_PAGE_ALIGN(info->brk + info->reserve_brk);
target_munmap(start_brk, end_brk - start_brk);
}

return 0;
}

Expand Down
41 changes: 41 additions & 0 deletions linux-user/ioctls.h
Expand Up @@ -69,6 +69,29 @@
IOCTL(KDSETLED, 0, TYPE_INT)
IOCTL_SPECIAL(KDSIGACCEPT, 0, do_ioctl_kdsigaccept, TYPE_INT)

IOCTL(RTC_AIE_ON, 0, TYPE_NULL)
IOCTL(RTC_AIE_OFF, 0, TYPE_NULL)
IOCTL(RTC_UIE_ON, 0, TYPE_NULL)
IOCTL(RTC_UIE_OFF, 0, TYPE_NULL)
IOCTL(RTC_PIE_ON, 0, TYPE_NULL)
IOCTL(RTC_PIE_OFF, 0, TYPE_NULL)
IOCTL(RTC_WIE_ON, 0, TYPE_NULL)
IOCTL(RTC_WIE_OFF, 0, TYPE_NULL)
IOCTL(RTC_ALM_READ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_rtc_time)))
IOCTL(RTC_ALM_SET, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtc_time)))
IOCTL(RTC_RD_TIME, IOC_R, MK_PTR(MK_STRUCT(STRUCT_rtc_time)))
IOCTL(RTC_SET_TIME, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtc_time)))
IOCTL(RTC_IRQP_READ, IOC_R, MK_PTR(TYPE_ULONG))
IOCTL(RTC_IRQP_SET, IOC_W, TYPE_ULONG)
IOCTL(RTC_EPOCH_READ, IOC_R, MK_PTR(TYPE_ULONG))
IOCTL(RTC_EPOCH_SET, IOC_W, TYPE_ULONG)
IOCTL(RTC_WKALM_RD, IOC_R, MK_PTR(MK_STRUCT(STRUCT_rtc_wkalrm)))
IOCTL(RTC_WKALM_SET, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtc_wkalrm)))
IOCTL(RTC_PLL_GET, IOC_R, MK_PTR(MK_STRUCT(STRUCT_rtc_pll_info)))
IOCTL(RTC_PLL_SET, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtc_pll_info)))
IOCTL(RTC_VL_READ, IOC_R, MK_PTR(TYPE_INT))
IOCTL(RTC_VL_CLR, 0, TYPE_NULL)

IOCTL(BLKROSET, IOC_W, MK_PTR(TYPE_INT))
IOCTL(BLKROGET, IOC_R, MK_PTR(TYPE_INT))
IOCTL(BLKRRPART, 0, TYPE_NULL)
Expand Down Expand Up @@ -114,7 +137,13 @@

IOCTL(FDMSGON, 0, TYPE_NULL)
IOCTL(FDMSGOFF, 0, TYPE_NULL)
IOCTL(FDSETEMSGTRESH, 0, TYPE_NULL)
IOCTL(FDFMTBEG, 0, TYPE_NULL)
IOCTL(FDFMTTRK, IOC_W, MK_PTR(MK_STRUCT(STRUCT_format_descr)))
IOCTL(FDFMTEND, 0, TYPE_NULL)
IOCTL(FDFLUSH, 0, TYPE_NULL)
IOCTL(FDSETMAXERRS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_floppy_max_errors)))
IOCTL(FDGETMAXERRS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_floppy_max_errors)))
IOCTL(FDRESET, 0, TYPE_NULL)
IOCTL(FDRAWCMD, 0, TYPE_NULL)
IOCTL(FDTWADDLE, 0, TYPE_NULL)
Expand All @@ -138,6 +167,12 @@

IOCTL(FS_IOC_GETFLAGS, IOC_R, MK_PTR(TYPE_INT))
IOCTL(FS_IOC_SETFLAGS, IOC_W, MK_PTR(TYPE_INT))
IOCTL(FS_IOC_GETVERSION, IOC_R, MK_PTR(TYPE_INT))
IOCTL(FS_IOC_SETVERSION, IOC_W, MK_PTR(TYPE_INT))
IOCTL(FS_IOC32_GETFLAGS, IOC_R, MK_PTR(TYPE_INT))
IOCTL(FS_IOC32_SETFLAGS, IOC_W, MK_PTR(TYPE_INT))
IOCTL(FS_IOC32_GETVERSION, IOC_R, MK_PTR(TYPE_INT))
IOCTL(FS_IOC32_SETVERSION, IOC_W, MK_PTR(TYPE_INT))

#ifdef CONFIG_USBFS
/* USB ioctls */
Expand Down Expand Up @@ -522,3 +557,9 @@
IOCTL_IGNORE(TIOCSTART)
IOCTL_IGNORE(TIOCSTOP)
#endif

#ifdef CONFIG_KCOV
IOCTL(KCOV_ENABLE, 0, TYPE_NULL)
IOCTL(KCOV_DISABLE, 0, TYPE_NULL)
IOCTL(KCOV_INIT_TRACE, IOC_R, TYPE_ULONG)
#endif
1 change: 1 addition & 0 deletions linux-user/qemu.h
Expand Up @@ -35,6 +35,7 @@ struct image_info {
abi_ulong end_data;
abi_ulong start_brk;
abi_ulong brk;
abi_ulong reserve_brk;
abi_ulong start_mmap;
abi_ulong start_stack;
abi_ulong stack_limit;
Expand Down
6 changes: 6 additions & 0 deletions linux-user/syscall.c
Expand Up @@ -73,6 +73,9 @@
#ifdef CONFIG_SENDFILE
#include <sys/sendfile.h>
#endif
#ifdef CONFIG_KCOV
#include <sys/kcov.h>
#endif

#define termios host_termios
#define winsize host_winsize
Expand Down Expand Up @@ -107,6 +110,7 @@
#include <netpacket/packet.h>
#include <linux/netlink.h>
#include <linux/if_alg.h>
#include <linux/rtc.h>
#include "linux_loop.h"
#include "uname.h"

Expand Down Expand Up @@ -5175,6 +5179,8 @@ static abi_long do_ioctl(int fd, int cmd, abi_long arg)
break;
case TYPE_PTRVOID:
case TYPE_INT:
case TYPE_LONG:
case TYPE_ULONG:
ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
break;
case TYPE_PTR:
Expand Down
59 changes: 56 additions & 3 deletions linux-user/syscall_defs.h
Expand Up @@ -763,6 +763,42 @@ struct target_pollfd {
#define TARGET_KDSETLED 0x4B32 /* set led state [lights, not flags] */
#define TARGET_KDSIGACCEPT 0x4B4E

struct target_rtc_pll_info {
int pll_ctrl;
int pll_value;
int pll_max;
int pll_min;
int pll_posmult;
int pll_negmult;
abi_long pll_clock;
};

/* real time clock ioctls */
#define TARGET_RTC_AIE_ON TARGET_IO('p', 0x01)
#define TARGET_RTC_AIE_OFF TARGET_IO('p', 0x02)
#define TARGET_RTC_UIE_ON TARGET_IO('p', 0x03)
#define TARGET_RTC_UIE_OFF TARGET_IO('p', 0x04)
#define TARGET_RTC_PIE_ON TARGET_IO('p', 0x05)
#define TARGET_RTC_PIE_OFF TARGET_IO('p', 0x06)
#define TARGET_RTC_WIE_ON TARGET_IO('p', 0x0f)
#define TARGET_RTC_WIE_OFF TARGET_IO('p', 0x10)
#define TARGET_RTC_ALM_READ TARGET_IOR('p', 0x08, struct rtc_time)
#define TARGET_RTC_ALM_SET TARGET_IOW('p', 0x07, struct rtc_time)
#define TARGET_RTC_RD_TIME TARGET_IOR('p', 0x09, struct rtc_time)
#define TARGET_RTC_SET_TIME TARGET_IOW('p', 0x0a, struct rtc_time)
#define TARGET_RTC_IRQP_READ TARGET_IOR('p', 0x0b, abi_ulong)
#define TARGET_RTC_IRQP_SET TARGET_IOW('p', 0x0c, abi_ulong)
#define TARGET_RTC_EPOCH_READ TARGET_IOR('p', 0x0d, abi_ulong)
#define TARGET_RTC_EPOCH_SET TARGET_IOW('p', 0x0e, abi_ulong)
#define TARGET_RTC_WKALM_RD TARGET_IOR('p', 0x10, struct rtc_wkalrm)
#define TARGET_RTC_WKALM_SET TARGET_IOW('p', 0x0f, struct rtc_wkalrm)
#define TARGET_RTC_PLL_GET TARGET_IOR('p', 0x11, \
struct target_rtc_pll_info)
#define TARGET_RTC_PLL_SET TARGET_IOW('p', 0x12, \
struct target_rtc_pll_info)
#define TARGET_RTC_VL_READ TARGET_IOR('p', 0x13, int)
#define TARGET_RTC_VL_CLR TARGET_IO('p', 0x14)

#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SH4) || \
defined(TARGET_XTENSA)
#define TARGET_FIOGETOWN TARGET_IOR('f', 123, int)
Expand Down Expand Up @@ -899,7 +935,13 @@ struct target_pollfd {

#define TARGET_FDMSGON TARGET_IO(2, 0x45)
#define TARGET_FDMSGOFF TARGET_IO(2, 0x46)
#define TARGET_FDFMTBEG TARGET_IO(2, 0x47)
#define TARGET_FDFMTTRK TARGET_IOW(2, 0x48, struct format_descr)
#define TARGET_FDFMTEND TARGET_IO(2, 0x49)
#define TARGET_FDSETEMSGTRESH TARGET_IO(2, 0x4a)
#define TARGET_FDFLUSH TARGET_IO(2, 0x4b)
#define TARGET_FDSETMAXERRS TARGET_IOW(2, 0x4c, struct floppy_max_errors)
#define TARGET_FDGETMAXERRS TARGET_IOR(2, 0x0e, struct floppy_max_errors)
#define TARGET_FDRESET TARGET_IO(2, 0x54)
#define TARGET_FDRAWCMD TARGET_IO(2, 0x58)
#define TARGET_FDTWADDLE TARGET_IO(2, 0x59)
Expand All @@ -911,13 +953,19 @@ struct target_pollfd {
#define TARGET_FICLONE TARGET_IOW(0x94, 9, int)
#define TARGET_FICLONERANGE TARGET_IOW(0x94, 13, struct file_clone_range)

/* Note that the ioctl numbers claim type "long" but the actual type
* used by the kernel is "int".
/*
* Note that the ioctl numbers for FS_IOC_<GET|SET><FLAGS|VERSION>
* claim type "long" but the actual type used by the kernel is "int".
*/
#define TARGET_FS_IOC_GETFLAGS TARGET_IOR('f', 1, abi_long)
#define TARGET_FS_IOC_SETFLAGS TARGET_IOW('f', 2, abi_long)

#define TARGET_FS_IOC_GETVERSION TARGET_IOR('v', 1, abi_long)
#define TARGET_FS_IOC_SETVERSION TARGET_IOW('v', 2, abi_long)
#define TARGET_FS_IOC_FIEMAP TARGET_IOWR('f',11,struct fiemap)
#define TARGET_FS_IOC32_GETFLAGS TARGET_IOR('f', 1, int)
#define TARGET_FS_IOC32_SETFLAGS TARGET_IOW('f', 2, int)
#define TARGET_FS_IOC32_GETVERSION TARGET_IOR('v', 1, int)
#define TARGET_FS_IOC32_SETVERSION TARGET_IOW('v', 2, int)

/* usb ioctls */
#define TARGET_USBDEVFS_CONTROL TARGET_IOWRU('U', 0)
Expand Down Expand Up @@ -2422,6 +2470,11 @@ struct target_mtpos {
#define TARGET_MTIOCGET TARGET_IOR('m', 2, struct target_mtget)
#define TARGET_MTIOCPOS TARGET_IOR('m', 3, struct target_mtpos)

/* kcov ioctls */
#define TARGET_KCOV_ENABLE TARGET_IO('c', 100)
#define TARGET_KCOV_DISABLE TARGET_IO('c', 101)
#define TARGET_KCOV_INIT_TRACE TARGET_IOR('c', 1, abi_ulong)

struct target_sysinfo {
abi_long uptime; /* Seconds since boot */
abi_ulong loads[3]; /* 1, 5, and 15 minute load averages */
Expand Down
37 changes: 37 additions & 0 deletions linux-user/syscall_types.h
Expand Up @@ -255,12 +255,49 @@ STRUCT(blkpg_partition,
MK_ARRAY(TYPE_CHAR, BLKPG_DEVNAMELTH), /* devname */
MK_ARRAY(TYPE_CHAR, BLKPG_VOLNAMELTH)) /* volname */

STRUCT(rtc_time,
TYPE_INT, /* tm_sec */
TYPE_INT, /* tm_min */
TYPE_INT, /* tm_hour */
TYPE_INT, /* tm_mday */
TYPE_INT, /* tm_mon */
TYPE_INT, /* tm_year */
TYPE_INT, /* tm_wday */
TYPE_INT, /* tm_yday */
TYPE_INT) /* tm_isdst */

STRUCT(rtc_wkalrm,
TYPE_CHAR, /* enabled */
TYPE_CHAR, /* pending */
MK_STRUCT(STRUCT_rtc_time)) /* time */

STRUCT(rtc_pll_info,
TYPE_INT, /* pll_ctrl */
TYPE_INT, /* pll_value */
TYPE_INT, /* pll_max */
TYPE_INT, /* pll_min */
TYPE_INT, /* pll_posmult */
TYPE_INT, /* pll_negmult */
TYPE_LONG) /* pll_clock */

STRUCT(blkpg_ioctl_arg,
TYPE_INT, /* op */
TYPE_INT, /* flags */
TYPE_INT, /* datalen */
TYPE_PTRVOID) /* data */

STRUCT(format_descr,
TYPE_INT, /* device */
TYPE_INT, /* head */
TYPE_INT) /* track */

STRUCT(floppy_max_errors,
TYPE_INT, /* abort */
TYPE_INT, /* read_track */
TYPE_INT, /* reset */
TYPE_INT, /* recal */
TYPE_INT) /* reporting */

#if defined(CONFIG_USBFS)
/* usb device ioctls */
STRUCT(usbdevfs_ctrltransfer,
Expand Down

0 comments on commit b7c359c

Please sign in to comment.