aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-01-23 14:38:43 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-01-23 14:38:43 +0000
commitb7c359c748a2e3ccb97a184b9739feb2cd48de2f (patch)
treeb08fefe2ba5816d620286165bf3fa006bfb84a2a
parent7cea426c1d2e12777a2e61d7970044981ff82aa8 (diff)
parenta7b09746679c1815115249ec69197e454efdfb15 (diff)
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-5.0-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>
-rwxr-xr-xconfigure9
-rw-r--r--linux-user/elfload.c75
-rw-r--r--linux-user/ioctls.h41
-rw-r--r--linux-user/qemu.h1
-rw-r--r--linux-user/syscall.c6
-rw-r--r--linux-user/syscall_defs.h59
-rw-r--r--linux-user/syscall_types.h37
7 files changed, 207 insertions, 21 deletions
diff --git a/configure b/configure
index 557e4382ea..d91eab4d65 100755
--- a/configure
+++ b/configure
@@ -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
@@ -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
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 07b16cc0f4..f3080a1635 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -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
@@ -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) {
@@ -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;
@@ -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;
}
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index c6b9d6ad66..73dcc761e6 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -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)
@@ -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)
@@ -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 */
@@ -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
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index f6f5fe5fbb..560a68090e 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -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;
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 249e4b95fc..d60142f069 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -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
@@ -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"
@@ -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:
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 98c2119de9..9b61ae8547 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -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)
@@ -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)
@@ -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)
@@ -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 */
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index 4e36983826..5ba4155047 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -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,