From dae8ca738c37c7ca619f575de7a88823db17976a Mon Sep 17 00:00:00 2001 From: rofl0r Date: Thu, 6 Mar 2014 00:26:03 +0100 Subject: [PATCH] x32: fix sysinfo() the kernel uses long longs in the struct, but the documentation says they're long. so we need to fixup the mismatch between the userspace and kernelspace structs. since the struct offers a mem_unit member, we can avoid truncation by adjusting that value. --- arch/x32/src/sysinfo.c | 47 +++++++++++++++++++++++++++++++++++++++++ src/linux/x32/sysinfo.s | 5 +++++ 2 files changed, 52 insertions(+) create mode 100644 arch/x32/src/sysinfo.c create mode 100644 src/linux/x32/sysinfo.s diff --git a/arch/x32/src/sysinfo.c b/arch/x32/src/sysinfo.c new file mode 100644 index 00000000..0f11cf3c --- /dev/null +++ b/arch/x32/src/sysinfo.c @@ -0,0 +1,47 @@ +#include +#include "syscall.h" + +#define klong long long +#define kulong unsigned long long + +struct kernel_sysinfo { + klong uptime; + kulong loads[3]; + kulong totalram; + kulong freeram; + kulong sharedram; + kulong bufferram; + kulong totalswap; + kulong freeswap; + short procs; + short pad; + kulong totalhigh; + kulong freehigh; + unsigned mem_unit; +}; + +int __x32_sysinfo(struct sysinfo *info) +{ + struct kernel_sysinfo tmp; + int ret = syscall(SYS_sysinfo, &tmp); + if(ret == -1) return ret; + info->uptime = tmp.uptime; + info->loads[0] = tmp.loads[0]; + info->loads[1] = tmp.loads[1]; + info->loads[2] = tmp.loads[2]; + kulong shifts; + kulong max = tmp.totalram | tmp.totalswap; + __asm__("bsr %1,%0" : "=r"(shifts) : "r"(max)); + shifts = shifts >= 32 ? shifts - 31 : 0; + info->totalram = tmp.totalram >> shifts; + info->freeram = tmp.freeram >> shifts; + info->sharedram = tmp.sharedram >> shifts; + info->bufferram = tmp.bufferram >> shifts; + info->totalswap = tmp.totalswap >> shifts; + info->freeswap = tmp.freeswap >> shifts; + info->procs = tmp.procs ; + info->totalhigh = tmp.totalhigh >> shifts; + info->freehigh = tmp.freehigh >> shifts; + info->mem_unit = (tmp.mem_unit ? tmp.mem_unit : 1) << shifts; + return ret; +} diff --git a/src/linux/x32/sysinfo.s b/src/linux/x32/sysinfo.s new file mode 100644 index 00000000..43c378c1 --- /dev/null +++ b/src/linux/x32/sysinfo.s @@ -0,0 +1,5 @@ +.text +.global sysinfo +.type sysinfo,@function +sysinfo: + jmp __x32_sysinfo