Preparation for including asm code from pq-code-package. Subsequent CLs will make use of this. Bug: 503700354 Change-Id: I28ed40a5517dc4e5133797e47906b8f56a6a6964 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/98028 Commit-Queue: Rudolf Polzer <rpolzer@google.com> Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Xiangfei Ding <xfding@google.com>
diff --git a/crypto/perlasm/PQCodePackage.pm b/crypto/perlasm/PQCodePackage.pm new file mode 100644 index 0000000..a9a41cc --- /dev/null +++ b/crypto/perlasm/PQCodePackage.pm
@@ -0,0 +1,112 @@ +package PQCodePackage; + +use strict; +use warnings; + +# Function to adapt assembly code from pq-code-package to BoringSSL usage. +# Should be kept as simple as possible, and maybe even become an identity +# function to just mark the origin of an assembly string. +sub asm { + my ($asm) = @_; + + # BoringSSL does not promise alignment for the key data. + $asm =~ s/\bvmovdqa\b/vmovdqu/g; + + return $asm; +} + +# TODO(crbug.com/33072965): Replace by a common approach. +# +# Adapter to use pq-code-package asm functions (which are red zone less SysV +# ABI) from BoringSSL. +# +# Handles register saving and argument remapping. +# +# Function must not call any non-SysV-ABI functions, and if it calls any +# SysV-ABI functions, $num_xmms must include the xmm registers they clobber +# too. +# +# Arguments: +# $win64: Whether compiling for Windows. +# $num_xmms: Number of xmm registers starting with xmm6 that get clobbered. +# $num_args: Number of arguments the function takes (at most 4). +sub abi_enter { + my ($win64, $num_xmms, $num_args) = @_; + my $out = ""; + if ($win64) { + $out .= " .seh_startproc\n"; + # Stack layout: xmm6@rsp xmm7 xmm8 ... rdi rsi padding returnaddress. + # Padding needed to align the xmm registers to 16 bytes boundaries. + my $stack_alloc = 16 + $num_xmms * 16 + 8; + $out .= " subq\t\$$stack_alloc, %rsp\n"; + $out .= " .seh_stackalloc\t$stack_alloc\n"; + + my $rdi_off = $num_xmms * 16; + my $rsi_off = $rdi_off + 8; + $out .= " movq\t%rdi, $rdi_off(%rsp)\n"; + $out .= " .seh_savereg\t%rdi, $rdi_off\n"; + $out .= " movq\t%rsi, $rsi_off(%rsp)\n"; + $out .= " .seh_savereg\t%rsi, $rsi_off\n"; + + for (my $i = 0; $i < $num_xmms; $i++) { + my $reg = 6 + $i; + my $off = $i * 16; + $out .= " vmovdqa\t%xmm$reg, $off(%rsp)\n"; + $out .= " .seh_savexmm\t%xmm$reg, $off\n"; + } + $out .= " .seh_endprologue\n"; + + # Map arguments. Funny ordering to spread out data dependencies. + $out .= " movq\t%rdx, %rsi\n" + if $num_args >= 2; + $out .= " movq\t%rcx, %rdi\n" + if $num_args >= 1; + $out .= " movq\t%r8, %rdx\n" + if $num_args >= 3; + $out .= " movq\t%r9, %rcx\n" + if $num_args >= 4; + die "abi_enter with invalid argument count: got $num_args, want <= 4" + if $num_args > 4; + } + return $out; +} + +# TODO(crbug.com/33072965): Replace by a common approach. +# +# Adapter to use pq-code-package asm functions (which are red zone less SysV +# ABI) from BoringSSL. +# +# Handles register restoring and AVX2 zeroing. +# +# Arguments: +# $win64: Whether compiling for Windows. +# $num_xmms: Number of xmm registers starting with xmm6 that get clobbered. +# Must match the argument to `abi_enter`. +sub abi_exit { + my ($win64, $num_xmms) = @_; + my $out = ""; + $out .= " vzeroupper\n"; + if ($win64) { + my $stack_alloc = 16 + $num_xmms * 16 + 8; + + for (my $i = 0; $i < $num_xmms; $i++) { + my $reg = 6 + $i; + my $off = $i * 16; + $out .= " vmovdqa\t$off(%rsp), %xmm$reg\n"; + } + + my $rdi_off = $num_xmms * 16; + my $rsi_off = $rdi_off + 8; + $out .= " movq\t$rdi_off(%rsp), %rdi\n"; + $out .= " movq\t$rsi_off(%rsp), %rsi\n"; + + $out .= " addq\t\$$stack_alloc, %rsp\n"; + } + $out .= " ret\n"; + if ($win64) { + $out .= " .seh_endproc\n"; + } + return $out; +} + +1;
diff --git a/crypto/perlasm/x86_64-xlate.pl b/crypto/perlasm/x86_64-xlate.pl index 508d36f..affebf1 100755 --- a/crypto/perlasm/x86_64-xlate.pl +++ b/crypto/perlasm/x86_64-xlate.pl
@@ -130,7 +130,7 @@ $self->{sz} = $2; } elsif ($self->{op} =~ /call|jmp|^rdrand$/) { $self->{sz} = ""; - } elsif ($self->{op} =~ /^p/ && $' !~ /^(ush|op|insrw)/) { # SSEn + } elsif ($self->{op} =~ /^p/ && $' !~ /^(ush|op|insrw|ext[ql]?$|dep[ql]?$)/) { # SSEn $self->{sz} = ""; } elsif ($self->{op} =~ /^[vk]/) { # VEX or k* such as kmov $self->{sz} = "";
diff --git a/util/pregenerate/build.go b/util/pregenerate/build.go index e3f732b..4951e04 100644 --- a/util/pregenerate/build.go +++ b/util/pregenerate/build.go
@@ -57,6 +57,25 @@ Args []string `json:"args,omitempty"` } +// findThirdParty locates the deepest package directory `dir` is in - either `dir` itself, or a subdirectory of a `third_party` directory. +func findThirdParty(dir string) string { + for { + parent := path.Dir(dir) + if path.Base(parent) == "third_party" { + return dir + } + if parent == dir { + return dir + } + dir = parent + } +} + +// matchThirdParty returns an edited form of the `dst` path so it has the same `third_party` prefix as `src`. +func matchThirdParty(src, dst string) string { + return path.Join(findThirdParty(src), dst) +} + // Pregenerate converts an input target to an output target. It returns the // result alongside a list of tasks that must be run to build the referenced // files. @@ -110,6 +129,7 @@ dst = strings.TrimSuffix(path.Base(p.Src), ".pl") } dst = path.Join("gen", name, dst+fileSuffix) + dst = matchThirdParty(p.Src, dst) args = append(slices.Clone(args), p.Args...) addTask(list, NewPerlasmTask(dst, p.Src, args)) return dst
diff --git a/util/pregenerate/task.go b/util/pregenerate/task.go index c6bc71e..bd38a75 100644 --- a/util/pregenerate/task.go +++ b/util/pregenerate/task.go
@@ -140,6 +140,7 @@ defer os.Remove(out.Name()) args := make([]string, 0, 2+len(perlasmArgs)) + args = append(args, "-Icrypto/perlasm") args = append(args, filepath.FromSlash(src)) args = append(args, perlasmArgs...) args = append(args, out.Name())