git: 64007b000a2f - main - makesyscalls: handle 64-bit args on 32-bit

From: Brooks Davis <brooks_at_FreeBSD.org>
Date: Mon, 22 Nov 2021 22:37:53 UTC
The branch main has been updated by brooks:

URL: https://cgit.FreeBSD.org/src/commit/?id=64007b000a2fdbac64c35aa05dd192609325a0a3

commit 64007b000a2fdbac64c35aa05dd192609325a0a3
Author:     Brooks Davis <brooks@FreeBSD.org>
AuthorDate: 2021-11-22 22:36:57 +0000
Commit:     Brooks Davis <brooks@FreeBSD.org>
CommitDate: 2021-11-22 22:36:57 +0000

    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
---
 sys/tools/makesyscalls.lua | 106 +++++++++++++++++++++++++++++++++++++--------
 1 file changed, 87 insertions(+), 19 deletions(-)

diff --git a/sys/tools/makesyscalls.lua b/sys/tools/makesyscalls.lua
index a5387463e4e2..1e66a6b319f3 100644
--- a/sys/tools/makesyscalls.lua
+++ b/sys/tools/makesyscalls.lua
@@ -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']))