mirror of https://github.com/xqemu/xqemu.git
linux-user patches for 2.4 softfreeze
second spin with ioctl patch refreshed -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIVAwUAVX/KMrRIkN7ePJvAAQg02g/+Ny0e+7sZd1ALgLcbxnP8qUgAYKIR0xbl 4iwfJjO8YWeD2x6EkEcb62nPD+ozL6of7DcuoYMeo6BFgZkxkUsGwO+W5N81AJJF pF9eH/DQwQa6kOUbB2aUIdxR/q1pJ62UKEK8jqfqAtGkSL7r1a4cOQgW8gOPIorv +lKbN+NYjZM/Ub11wYiqW579d3vfsFqrFeLjDqLv5qRyIY+O/Jr8LgqokAurJH05 WcRuw2mtLWEQZESNdMox2G3UQ6dqZUk6j/ipIVduzfHkmZZqAUrJeKHV2ZTu9rWs 7+Daihremp46ZLGGMgarG6/arDrqplmkWOshT60bm9J6SDiE20QyWJ6YymukGUre rGbyk9RFBvamzMLns4jdVduFMOFWzgedVSA0cbo/VvuZriRxkzq8fW0o6I72Vlpf OoEoY+t1M2CJOnOvjuU3z2iu0AwizJ9Xz18pOVHCovSPTWMmItfOt9CVexJIvLKH DwqsaoaEdao5r5SoxBOM+l0vrh4QK6vLldBQaF46OhEyH3xySMD80cEsSM9lJWQg lcGFmyQloc57TF0bLeJ5vxBwFBNRUYaKK698PJCG4wqhF+X0DxbFnY5q1QpfUZWv tlabnqGt9sadYbjJmEHlc9dhXzXa76fvRgIhjlK014g9jL3KAnVWA2q4w2nQOGk0 Yws7IBXoynA= =tTJW -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/riku/tags/pull-linux-user-20150616' into staging linux-user patches for 2.4 softfreeze second spin with ioctl patch refreshed # gpg: Signature made Tue Jun 16 08:03:14 2015 BST using RSA key ID DE3C9BC0 # gpg: Good signature from "Riku Voipio <riku.voipio@iki.fi>" # gpg: aka "Riku Voipio <riku.voipio@linaro.org>" * remotes/riku/tags/pull-linux-user-20150616: linux-user: ioctl() command type is int linux-user: fix the breakpoint inheritance in spawned threads linux-user: use __get_user and __put_user in cmsg conversions linux-user: Fix length handling in host_to_target_cmsg linux-user: Use abi_ulong for TARGET_ELF_PAGESTART linux-user: Allocate thunk size dynamically Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
4316536bf4
|
@ -74,7 +74,7 @@ const argtype *thunk_convert(void *dst, const void *src,
|
|||
const argtype *type_ptr, int to_host);
|
||||
#ifndef NO_THUNK_TYPE_SIZE
|
||||
|
||||
extern StructEntry struct_entries[];
|
||||
extern StructEntry *struct_entries;
|
||||
|
||||
int thunk_type_size_array(const argtype *type_ptr, int is_host);
|
||||
int thunk_type_align_array(const argtype *type_ptr, int is_host);
|
||||
|
@ -186,4 +186,6 @@ unsigned int target_to_host_bitmask(unsigned int x86_mask,
|
|||
unsigned int host_to_target_bitmask(unsigned int alpha_mask,
|
||||
const bitmask_transtbl * trans_tbl);
|
||||
|
||||
void thunk_init(unsigned int max_structs);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1256,7 +1256,8 @@ struct exec
|
|||
|
||||
/* Necessary parameters */
|
||||
#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
|
||||
#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
|
||||
#define TARGET_ELF_PAGESTART(_v) ((_v) & \
|
||||
~(abi_ulong)(TARGET_ELF_EXEC_PAGESIZE-1))
|
||||
#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
|
||||
|
||||
#define DLINFO_ITEMS 14
|
||||
|
|
|
@ -3459,8 +3459,8 @@ CPUArchState *cpu_copy(CPUArchState *env)
|
|||
/* Clone all break/watchpoints.
|
||||
Note: Once we support ptrace with hw-debug register access, make sure
|
||||
BP_CPU break/watchpoints are handled correctly on clone. */
|
||||
QTAILQ_INIT(&cpu->breakpoints);
|
||||
QTAILQ_INIT(&cpu->watchpoints);
|
||||
QTAILQ_INIT(&new_cpu->breakpoints);
|
||||
QTAILQ_INIT(&new_cpu->watchpoints);
|
||||
QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
|
||||
cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL);
|
||||
}
|
||||
|
|
|
@ -1202,6 +1202,15 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
|
|||
space += CMSG_SPACE(len);
|
||||
if (space > msgh->msg_controllen) {
|
||||
space -= CMSG_SPACE(len);
|
||||
/* This is a QEMU bug, since we allocated the payload
|
||||
* area ourselves (unlike overflow in host-to-target
|
||||
* conversion, which is just the guest giving us a buffer
|
||||
* that's too small). It can't happen for the payload types
|
||||
* we currently support; if it becomes an issue in future
|
||||
* we would need to improve our allocation strategy to
|
||||
* something more intelligent than "twice the size of the
|
||||
* target buffer we're reading from".
|
||||
*/
|
||||
gemu_log("Host cmsg overflow\n");
|
||||
break;
|
||||
}
|
||||
|
@ -1219,17 +1228,18 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
|
|||
int *target_fd = (int *)target_data;
|
||||
int i, numfds = len / sizeof(int);
|
||||
|
||||
for (i = 0; i < numfds; i++)
|
||||
fd[i] = tswap32(target_fd[i]);
|
||||
for (i = 0; i < numfds; i++) {
|
||||
__get_user(fd[i], target_fd + i);
|
||||
}
|
||||
} else if (cmsg->cmsg_level == SOL_SOCKET
|
||||
&& cmsg->cmsg_type == SCM_CREDENTIALS) {
|
||||
struct ucred *cred = (struct ucred *)data;
|
||||
struct target_ucred *target_cred =
|
||||
(struct target_ucred *)target_data;
|
||||
|
||||
__put_user(target_cred->pid, &cred->pid);
|
||||
__put_user(target_cred->uid, &cred->uid);
|
||||
__put_user(target_cred->gid, &cred->gid);
|
||||
__get_user(cred->pid, &target_cred->pid);
|
||||
__get_user(cred->uid, &target_cred->uid);
|
||||
__get_user(cred->gid, &target_cred->gid);
|
||||
} else {
|
||||
gemu_log("Unsupported ancillary data: %d/%d\n",
|
||||
cmsg->cmsg_level, cmsg->cmsg_type);
|
||||
|
@ -1267,11 +1277,16 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
|
|||
void *target_data = TARGET_CMSG_DATA(target_cmsg);
|
||||
|
||||
int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
|
||||
int tgt_len, tgt_space;
|
||||
|
||||
space += TARGET_CMSG_SPACE(len);
|
||||
if (space > msg_controllen) {
|
||||
space -= TARGET_CMSG_SPACE(len);
|
||||
gemu_log("Target cmsg overflow\n");
|
||||
/* We never copy a half-header but may copy half-data;
|
||||
* this is Linux's behaviour in put_cmsg(). Note that
|
||||
* truncation here is a guest problem (which we report
|
||||
* to the guest via the CTRUNC bit), unlike truncation
|
||||
* in target_to_host_cmsg, which is a QEMU bug.
|
||||
*/
|
||||
if (msg_controllen < sizeof(struct cmsghdr)) {
|
||||
target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1281,8 +1296,35 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
|
|||
target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
|
||||
}
|
||||
target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
|
||||
target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(len));
|
||||
|
||||
tgt_len = TARGET_CMSG_LEN(len);
|
||||
|
||||
/* Payload types which need a different size of payload on
|
||||
* the target must adjust tgt_len here.
|
||||
*/
|
||||
switch (cmsg->cmsg_level) {
|
||||
case SOL_SOCKET:
|
||||
switch (cmsg->cmsg_type) {
|
||||
case SO_TIMESTAMP:
|
||||
tgt_len = sizeof(struct target_timeval);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg_controllen < tgt_len) {
|
||||
target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
|
||||
tgt_len = msg_controllen;
|
||||
}
|
||||
|
||||
/* We must now copy-and-convert len bytes of payload
|
||||
* into tgt_len bytes of destination space. Bear in mind
|
||||
* that in both source and destination we may be dealing
|
||||
* with a truncated value!
|
||||
*/
|
||||
switch (cmsg->cmsg_level) {
|
||||
case SOL_SOCKET:
|
||||
switch (cmsg->cmsg_type) {
|
||||
|
@ -1290,10 +1332,11 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
|
|||
{
|
||||
int *fd = (int *)data;
|
||||
int *target_fd = (int *)target_data;
|
||||
int i, numfds = len / sizeof(int);
|
||||
int i, numfds = tgt_len / sizeof(int);
|
||||
|
||||
for (i = 0; i < numfds; i++)
|
||||
target_fd[i] = tswap32(fd[i]);
|
||||
for (i = 0; i < numfds; i++) {
|
||||
__put_user(fd[i], target_fd + i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SO_TIMESTAMP:
|
||||
|
@ -1302,12 +1345,14 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
|
|||
struct target_timeval *target_tv =
|
||||
(struct target_timeval *)target_data;
|
||||
|
||||
if (len != sizeof(struct timeval))
|
||||
if (len != sizeof(struct timeval) ||
|
||||
tgt_len != sizeof(struct target_timeval)) {
|
||||
goto unimplemented;
|
||||
}
|
||||
|
||||
/* copy struct timeval to target */
|
||||
target_tv->tv_sec = tswapal(tv->tv_sec);
|
||||
target_tv->tv_usec = tswapal(tv->tv_usec);
|
||||
__put_user(tv->tv_sec, &target_tv->tv_sec);
|
||||
__put_user(tv->tv_usec, &target_tv->tv_usec);
|
||||
break;
|
||||
}
|
||||
case SCM_CREDENTIALS:
|
||||
|
@ -1330,9 +1375,19 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
|
|||
unimplemented:
|
||||
gemu_log("Unsupported ancillary data: %d/%d\n",
|
||||
cmsg->cmsg_level, cmsg->cmsg_type);
|
||||
memcpy(target_data, data, len);
|
||||
memcpy(target_data, data, MIN(len, tgt_len));
|
||||
if (tgt_len > len) {
|
||||
memset(target_data + len, 0, tgt_len - len);
|
||||
}
|
||||
}
|
||||
|
||||
target_cmsg->cmsg_len = tswapal(tgt_len);
|
||||
tgt_space = TARGET_CMSG_SPACE(tgt_len);
|
||||
if (msg_controllen < tgt_space) {
|
||||
tgt_space = msg_controllen;
|
||||
}
|
||||
msg_controllen -= tgt_space;
|
||||
space += tgt_space;
|
||||
cmsg = CMSG_NXTHDR(msgh, cmsg);
|
||||
target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
|
||||
}
|
||||
|
@ -3277,6 +3332,7 @@ static abi_long do_ipc(unsigned int call, abi_long first,
|
|||
#define STRUCT_SPECIAL(name) STRUCT_ ## name,
|
||||
enum {
|
||||
#include "syscall_types.h"
|
||||
STRUCT_MAX
|
||||
};
|
||||
#undef STRUCT
|
||||
#undef STRUCT_SPECIAL
|
||||
|
@ -3290,7 +3346,7 @@ enum {
|
|||
typedef struct IOCTLEntry IOCTLEntry;
|
||||
|
||||
typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
int fd, abi_long cmd, abi_long arg);
|
||||
int fd, int cmd, abi_long arg);
|
||||
|
||||
struct IOCTLEntry {
|
||||
int target_cmd;
|
||||
|
@ -3316,7 +3372,7 @@ struct IOCTLEntry {
|
|||
/ sizeof(struct fiemap_extent))
|
||||
|
||||
static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
int fd, abi_long cmd, abi_long arg)
|
||||
int fd, int cmd, abi_long arg)
|
||||
{
|
||||
/* The parameter for this ioctl is a struct fiemap followed
|
||||
* by an array of struct fiemap_extent whose size is set
|
||||
|
@ -3397,7 +3453,7 @@ static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
|
|||
#endif
|
||||
|
||||
static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
int fd, abi_long cmd, abi_long arg)
|
||||
int fd, int cmd, abi_long arg)
|
||||
{
|
||||
const argtype *arg_type = ie->arg_type;
|
||||
int target_size;
|
||||
|
@ -3491,7 +3547,7 @@ static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
|
|||
}
|
||||
|
||||
static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
|
||||
abi_long cmd, abi_long arg)
|
||||
int cmd, abi_long arg)
|
||||
{
|
||||
void *argptr;
|
||||
struct dm_ioctl *host_dm;
|
||||
|
@ -3716,7 +3772,7 @@ out:
|
|||
}
|
||||
|
||||
static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
|
||||
abi_long cmd, abi_long arg)
|
||||
int cmd, abi_long arg)
|
||||
{
|
||||
void *argptr;
|
||||
int target_size;
|
||||
|
@ -3769,7 +3825,7 @@ out:
|
|||
}
|
||||
|
||||
static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
int fd, abi_long cmd, abi_long arg)
|
||||
int fd, int cmd, abi_long arg)
|
||||
{
|
||||
const argtype *arg_type = ie->arg_type;
|
||||
const StructEntry *se;
|
||||
|
@ -3832,7 +3888,7 @@ static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
|
|||
}
|
||||
|
||||
static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
|
||||
int fd, abi_long cmd, abi_long arg)
|
||||
int fd, int cmd, abi_long arg)
|
||||
{
|
||||
int sig = target_to_host_signal(arg);
|
||||
return get_errno(ioctl(fd, ie->host_cmd, sig));
|
||||
|
@ -3849,7 +3905,7 @@ static IOCTLEntry ioctl_entries[] = {
|
|||
|
||||
/* ??? Implement proper locking for ioctls. */
|
||||
/* do_ioctl() Must return target values and target errnos. */
|
||||
static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
|
||||
static abi_long do_ioctl(int fd, int cmd, abi_long arg)
|
||||
{
|
||||
const IOCTLEntry *ie;
|
||||
const argtype *arg_type;
|
||||
|
@ -4879,6 +4935,8 @@ void syscall_init(void)
|
|||
int size;
|
||||
int i;
|
||||
|
||||
thunk_init(STRUCT_MAX);
|
||||
|
||||
#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
|
||||
#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
|
||||
#include "syscall_types.h"
|
||||
|
|
16
thunk.c
16
thunk.c
|
@ -25,10 +25,8 @@
|
|||
|
||||
//#define DEBUG
|
||||
|
||||
#define MAX_STRUCTS 128
|
||||
|
||||
/* XXX: make it dynamic */
|
||||
StructEntry struct_entries[MAX_STRUCTS];
|
||||
static unsigned int max_struct_entries;
|
||||
StructEntry *struct_entries;
|
||||
|
||||
static const argtype *thunk_type_next_ptr(const argtype *type_ptr);
|
||||
|
||||
|
@ -70,6 +68,7 @@ void thunk_register_struct(int id, const char *name, const argtype *types)
|
|||
StructEntry *se;
|
||||
int nb_fields, offset, max_align, align, size, i, j;
|
||||
|
||||
assert(id < max_struct_entries);
|
||||
se = struct_entries + id;
|
||||
|
||||
/* first we count the number of fields */
|
||||
|
@ -117,6 +116,8 @@ void thunk_register_struct_direct(int id, const char *name,
|
|||
const StructEntry *se1)
|
||||
{
|
||||
StructEntry *se;
|
||||
|
||||
assert(id < max_struct_entries);
|
||||
se = struct_entries + id;
|
||||
*se = *se1;
|
||||
se->name = name;
|
||||
|
@ -244,6 +245,7 @@ const argtype *thunk_convert(void *dst, const void *src,
|
|||
const argtype *field_types;
|
||||
const int *dst_offsets, *src_offsets;
|
||||
|
||||
assert(*type_ptr < max_struct_entries);
|
||||
se = struct_entries + *type_ptr++;
|
||||
if (se->convert[0] != NULL) {
|
||||
/* specific conversion is needed */
|
||||
|
@ -314,3 +316,9 @@ int thunk_type_align_array(const argtype *type_ptr, int is_host)
|
|||
return thunk_type_align(type_ptr, is_host);
|
||||
}
|
||||
#endif /* ndef NO_THUNK_TYPE_SIZE */
|
||||
|
||||
void thunk_init(unsigned int max_structs)
|
||||
{
|
||||
max_struct_entries = max_structs;
|
||||
struct_entries = g_new0(StructEntry, max_structs);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue