summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux-user/syscall_types.h4
-rw-r--r--thunk.c28
-rw-r--r--thunk.h28
3 files changed, 58 insertions, 2 deletions
diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
index fb8c9c980c..601618df98 100644
--- a/linux-user/syscall_types.h
+++ b/linux-user/syscall_types.h
@@ -83,9 +83,9 @@ STRUCT(mixer_info,
/* loop device ioctls */
STRUCT(loop_info,
TYPE_INT, /* lo_number */
- TYPE_SHORT, /* lo_device */
+ TYPE_OLDDEVT, /* lo_device */
TYPE_ULONG, /* lo_inode */
- TYPE_SHORT, /* lo_rdevice */
+ TYPE_OLDDEVT, /* lo_rdevice */
TYPE_INT, /* lo_offset */
TYPE_INT, /* lo_encrypt_type */
TYPE_INT, /* lo_encrypt_key_size */
diff --git a/thunk.c b/thunk.c
index 06571889ae..8ebbbb46b6 100644
--- a/thunk.c
+++ b/thunk.c
@@ -46,6 +46,7 @@ static inline const argtype *thunk_type_next(const argtype *type_ptr)
case TYPE_LONG:
case TYPE_ULONG:
case TYPE_PTRVOID:
+ case TYPE_OLDDEVT:
return type_ptr;
case TYPE_PTR:
return thunk_type_next_ptr(type_ptr);
@@ -188,6 +189,33 @@ const argtype *thunk_convert(void *dst, const void *src,
#else
#warning unsupported conversion
#endif
+ case TYPE_OLDDEVT:
+ {
+ uint64_t val = 0;
+ switch (thunk_type_size(type_ptr - 1, !to_host)) {
+ case 2:
+ val = *(uint16_t *)src;
+ break;
+ case 4:
+ val = *(uint32_t *)src;
+ break;
+ case 8:
+ val = *(uint64_t *)src;
+ break;
+ }
+ switch (thunk_type_size(type_ptr - 1, to_host)) {
+ case 2:
+ *(uint16_t *)dst = tswap16(val);
+ break;
+ case 4:
+ *(uint32_t *)dst = tswap32(val);
+ break;
+ case 8:
+ *(uint64_t *)dst = tswap64(val);
+ break;
+ }
+ break;
+ }
case TYPE_ARRAY:
{
int array_length, i, dst_size, src_size;
diff --git a/thunk.h b/thunk.h
index 9810743191..5be8f912f5 100644
--- a/thunk.h
+++ b/thunk.h
@@ -37,6 +37,7 @@ typedef enum argtype {
TYPE_PTR,
TYPE_ARRAY,
TYPE_STRUCT,
+ TYPE_OLDDEVT,
} argtype;
#define MK_PTR(type) TYPE_PTR, type
@@ -104,6 +105,31 @@ static inline int thunk_type_size(const argtype *type_ptr, int is_host)
return TARGET_ABI_BITS / 8;
}
break;
+ case TYPE_OLDDEVT:
+ if (is_host) {
+#if defined(HOST_X86_64)
+ return 8;
+#elif defined(HOST_ALPHA) || defined(HOST_IA64) || defined(HOST_MIPS) || \
+ defined(HOST_PARISC) || defined(HOST_SPARC64)
+ return 4;
+#elif defined(HOST_PPC)
+ return HOST_LONG_SIZE;
+#else
+ return 2;
+#endif
+ } else {
+#if defined(TARGET_X86_64)
+ return 8;
+#elif defined(TARGET_ALPHA) || defined(TARGET_IA64) || defined(TARGET_MIPS) || \
+ defined(TARGET_PARISC) || defined(TARGET_SPARC64)
+ return 4;
+#elif defined(TARGET_PPC)
+ return TARGET_ABI_BITS / 8;
+#else
+ return 2;
+#endif
+ }
+ break;
case TYPE_ARRAY:
size = type_ptr[1];
return size * thunk_type_size_array(type_ptr + 2, is_host);
@@ -141,6 +167,8 @@ static inline int thunk_type_align(const argtype *type_ptr, int is_host)
return TARGET_ABI_BITS / 8;
}
break;
+ case TYPE_OLDDEVT:
+ return thunk_type_size(type_ptr, is_host);
case TYPE_ARRAY:
return thunk_type_align_array(type_ptr + 2, is_host);
case TYPE_STRUCT: