makesyscalls: handle 64-bit args on 32-bit

On 32-bit architectures, 64-bit arguments are passed in pairs of
registers. On non-x86 architectures these arguments must be in evenly
aligned registers which necessiciates inserting a pad register into the
argument list. This has historically been supported by adding ifdefs
around padded and unpadded syscall defintions in syscalls.master.

In order to enable generation of 32-bit support files from the base
syscalls.master, pull this support in to makesyscalls.lua enabled by
adding pair_64bit to abi_flags.

The changes to sys_proto.h simply add #ifdef PAD64_REQUIRED
around pad arguments in struct <syscall>_args. In systrace_args(),
replace static syscall index values with post-incremented indexs
allowing a simple ifdef around the argument. Under -O1 or higher
code generation is identical. systrace_entry_setargdesc() is a bit
more complicated as we switch on argument indices.  Solve this
with some use of define/undef pairs to compute the correct indices.

Reviewed by:	kevans
This commit is contained in:
Brooks Davis 2021-11-22 22:36:57 +00:00
parent 79634eb90b
commit 64007b000a

View File

@ -167,6 +167,14 @@ local known_abi_flags = {
"[*][*]",
},
},
pair_64bit = {
value = 0x00000010,
exprs = {
"^dev_t[ ]*$",
"^id_t[ ]*$",
"^off_t[ ]*$",
},
},
}
local known_flags = {
@ -426,6 +434,11 @@ local function isptrarraytype(type)
return type:find("[*][*]") or type:find("[*][ ]*const[ ]*[*]")
end
-- Find types that are always 64-bits wide
local function is64bittype(type)
return type:find("^dev_t[ ]*$") or type:find("^id_t[ ]*$") or type:find("^off_t[ ]*$")
end
local process_syscall_def
-- These patterns are processed in order on any line that isn't empty.
@ -648,10 +661,27 @@ local function process_args(args)
abi_type_suffix)
end
funcargs[#funcargs + 1] = {
type = argtype,
name = argname,
}
if abi_changes("pair_64bit") and is64bittype(argtype) then
if #funcargs % 2 == 1 then
funcargs[#funcargs + 1] = {
type = "int",
name = "_pad",
}
end
funcargs[#funcargs + 1] = {
type = "uint32_t",
name = argname .. "1",
}
funcargs[#funcargs + 1] = {
type = "uint32_t",
name = argname .. "2",
}
else
funcargs[#funcargs + 1] = {
type = argtype,
name = argname,
}
end
end
::out::
@ -686,45 +716,62 @@ local function handle_noncompat(sysnum, thr_flag, flags, sysflags, rettype,
write_line("systrace", string.format(
"\t\tstruct %s *p = params;\n", argalias))
local argtype, argname
local argtype, argname, desc, padding
padding = ""
for idx, arg in ipairs(funcargs) do
argtype = arg["type"]
argname = arg["name"]
argtype = trim(argtype:gsub("__restrict$", ""), nil)
if argtype == "int" and argname == "_pad" and abi_changes("pair_64bit") then
write_line("systracetmp", "#ifdef PAD64_REQUIRED\n")
end
-- Pointer arg?
if argtype:find("*") then
write_line("systracetmp", string.format(
"\t\tcase %d:\n\t\t\tp = \"userland %s\";\n\t\t\tbreak;\n",
idx - 1, argtype))
desc = "userland " .. argtype
else
write_line("systracetmp", string.format(
"\t\tcase %d:\n\t\t\tp = \"%s\";\n\t\t\tbreak;\n",
idx - 1, argtype))
desc = argtype;
end
write_line("systracetmp", string.format(
"\t\tcase %d%s:\n\t\t\tp = \"%s\";\n\t\t\tbreak;\n",
idx - 1, padding, desc))
if argtype == "int" and argname == "_pad" and abi_changes("pair_64bit") then
padding = " - _P_"
write_line("systracetmp", "#define _P_ 0\n#else\n#define _P_ 1\n#endif\n")
end
if isptrtype(argtype) then
write_line("systrace", string.format(
"\t\tuarg[%d] = (%s)p->%s; /* %s */\n",
idx - 1, config["ptr_intptr_t_cast"],
"\t\tuarg[a++] = (%s)p->%s; /* %s */\n",
config["ptr_intptr_t_cast"],
argname, argtype))
elseif argtype == "union l_semun" then
write_line("systrace", string.format(
"\t\tuarg[%d] = p->%s.buf; /* %s */\n",
idx - 1, argname, argtype))
"\t\tuarg[a++] = p->%s.buf; /* %s */\n",
argname, argtype))
elseif argtype:sub(1,1) == "u" or argtype == "size_t" then
write_line("systrace", string.format(
"\t\tuarg[%d] = p->%s; /* %s */\n",
idx - 1, argname, argtype))
"\t\tuarg[a++] = p->%s; /* %s */\n",
argname, argtype))
else
if argtype == "int" and argname == "_pad" and abi_changes("pair_64bit") then
write_line("systrace", "#ifdef PAD64_REQUIRED\n")
end
write_line("systrace", string.format(
"\t\tiarg[%d] = p->%s; /* %s */\n",
idx - 1, argname, argtype))
"\t\tiarg[a++] = p->%s; /* %s */\n",
argname, argtype))
if argtype == "int" and argname == "_pad" and abi_changes("pair_64bit") then
write_line("systrace", "#endif\n")
end
end
end
write_line("systracetmp",
"\t\tdefault:\n\t\t\tbreak;\n\t\t};\n")
if padding ~= "" then
write_line("systracetmp", "#undef _P_\n\n")
end
write_line("systraceret", string.format([[
if (ndx == 0 || ndx == 1)
@ -743,11 +790,17 @@ local function handle_noncompat(sysnum, thr_flag, flags, sysflags, rettype,
argalias))
for _, v in ipairs(funcargs) do
local argname, argtype = v["name"], v["type"]
if argtype == "int" and argname == "_pad" and abi_changes("pair_64bit") then
write_line("sysarg", "#ifdef PAD64_REQUIRED\n")
end
write_line("sysarg", string.format(
"\tchar %s_l_[PADL_(%s)]; %s %s; char %s_r_[PADR_(%s)];\n",
argname, argtype,
argtype, argname,
argname, argtype))
if argtype == "int" and argname == "_pad" and abi_changes("pair_64bit") then
write_line("sysarg", "#endif\n")
end
end
write_line("sysarg", "};\n")
else
@ -1284,6 +1337,20 @@ struct thread;
]], generated_tag, config['os_id_keyword'], config['sysproto_h'],
config['sysproto_h']))
if abi_changes("pair_64bit") then
write_line("sysarg", string.format([[
#if !defined(PAD64_REQUIRED) && !defined(__amd64__)
#define PAD64_REQUIRED
#endif
]]))
end
if abi_changes("pair_64bit") then
write_line("systrace", string.format([[
#if !defined(PAD64_REQUIRED) && !defined(__amd64__)
#define PAD64_REQUIRED
#endif
]]))
end
for _, v in pairs(compat_options) do
write_line(v["tmp"], string.format("\n#ifdef %s\n\n", v["definition"]))
end
@ -1324,6 +1391,7 @@ static void
systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
{
int64_t *iarg = (int64_t *)uarg;
int a = 0;
switch (sysnum) {
]], generated_tag, config['os_id_keyword']))