This is an archive of the discontinued LLVM Phabricator instance.

[KMSAN] Enable on SystemZ
ClosedPublic

Authored by iii on Apr 17 2023, 6:12 PM.

Details

Summary

Enable -fsanitize=kernel-memory support in Clang.

The x86_64 ABI requires that shadow_origin_ptr_t must be returned via a
register pair, and the s390x ABI requires that it must be returned via
memory pointed to by a hidden parameter. Normally Clang takes care of
the ABI, but the sanitizers run long after it, so unfortunately they
have to duplicate the ABI logic.

Therefore add a special case for SystemZ and manually emit the
s390x-ABI-compliant calling sequences. Since it's only 2 architectures,
do not create a VarArgHelper-like abstraction layer.

The kernel functions are compiled with the "packed-stack" and
"use-soft-float" attributes. For the "packed-stack" functions, it's not
correct for copyRegSaveArea() to copy 160 bytes of shadow and origins,
since the save area is dynamically sized. Things are greatly simplified
by the fact that the vararg "use-soft-float" functions use precisely
56 bytes in order to save the argument registers to where va_arg() can
find them.

Make copyRegSaveArea() copy only 56 bytes in the "use-soft-float" case.
The "packed-stack" && !"use-soft-float" case has no practical uses at
the moment, so leave it for the future.

Add tests.

Diff Detail

Event Timeline

iii created this revision.Apr 17 2023, 6:12 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 17 2023, 6:12 PM
iii requested review of this revision.Apr 17 2023, 6:12 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptApr 17 2023, 6:12 PM

Do you have a working kernel patch for SystemZ?
I think we'd better name the functions taking the extra parameter differently - maybe at some point we'll even want them to coexist on certain architectures. Anyway, it might just look cleaner in the kernel code.

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
118

You are changing KMSAN API, so this comment needs to be updated.

142

Please update this comment as well.

750

Can we add a bool to MemorySanitizerPass to indicate whether or not we want to return the metadata as a pointer?
We'll then set it based on Triple::systemz once and check everywhere, making the code more readable.

1497

Have you considered using per-CPU data instead of this alloca (there might be pitfalls as well, so just curious).
Same question for passing a single struct vs. two separate allocas for shadow/origin.

llvm/test/Instrumentation/MemorySanitizer/SystemZ/basic-kernel.ll
7

This test should cover all the newly introduced API functions.

iii added a comment.Apr 18 2023, 2:03 AM

The kernel patch is currently WIP; I'm trying to get rid of false positives.
Just some examples of the findings so far:

  • s390x always uses separate address spaces for kernel and userspace, so we need to skip the addr < TASK_SIZE check in is_bad_asm_addr().
  • There is a 4k asm store, so the limit in __msan_instrument_asm_store() needs to be bumped.

There were a couple build issues with the common code too:

  • _PAGE_NX is called _PAGE_NOEXEC on s390x
  • asm/pgtable_64_types.h is called asm/pgtable.h on s390x
llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
118

The API stays exactly the same here; I haven't touched kernel function signatures.

What changes here is that I've implemented the s390x ABI for the KMSAN API.

142

Ok.

750

We could do that, but that's really the detail of the s390x ABI. Other platforms might have different conventions for large return values. That's why I didn't want to introduce generic concepts for this and highlight that it's s390x specific, where possible.

1497

Yes, but I was wondering if there was any benefit? I thought that maybe that would save a frame for leaf functions, but since we are calling KMSAN API, we already need one (and technically they are not leaf functions anymore).

Passing two separate allocas would actually change the API, as opposed to implementing the new ABI, so I wanted to avoid that for now, even if it were more efficient.

llvm/test/Instrumentation/MemorySanitizer/SystemZ/basic-kernel.ll
7

Ok.

glider added inline comments.Apr 18 2023, 2:47 AM
llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
118

Ahh, pardon my ignorance, I've had no idea s390x is doing that fancy stuff with a hidden parameter.
Perhaps you could elaborate on it a bit more in the patch description? (I already educated myself reading the s390x ABI spec and playing with Godbolt, but still).

It might be still worth mentioning in this comment that for s390x we emulate the ABI manually.

750

Ok, sounds good.

1497

Ok, got it. Given that this is actually the desired way to pass the struct parameters in SystemZ, it should be fine.

iii updated this revision to Diff 514692.Apr 18 2023, 10:58 AM
  • Better explain the ABI situation.
  • Extend the test.
iii marked 8 inline comments as done.Apr 18 2023, 10:59 AM
iii edited the summary of this revision. (Show Details)

LGTM with a nit.

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
750

I think people unfamiliar with the s390 ABI will still stumble upon this code.
Can you please add some comment along the lines of "On SystemZ, metadata hooks return the shadow/origin pair via an extra *MsanMetadata parameter"?

iii updated this revision to Diff 515266.Apr 20 2023, 3:06 AM
  • Add a comment to getOrInsertMsanMetadataFunction().
iii marked an inline comment as done.Apr 20 2023, 3:07 AM
eugenis accepted this revision.Apr 20 2023, 4:02 PM

LGTM

This revision is now accepted and ready to land.Apr 20 2023, 4:02 PM
MaskRay added inline comments.Apr 20 2023, 5:22 PM
llvm/test/Instrumentation/MemorySanitizer/SystemZ/basic-kernel.ll
13

; CHECK-LABEL: define {{[^@]+}}@Store1( to match the @Store definition, not calls.

MaskRay added inline comments.Apr 20 2023, 5:24 PM
llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp
1498

Just use 0.

Even 0u is better than (unsigned)0.

iii updated this revision to Diff 515661.Apr 21 2023, 2:37 AM
  • (unsigned)0 -> 0u (0 doesn't work, because the overload becomes ambiguous).
  • Improve matching in the testcase.
iii marked 2 inline comments as done.Apr 21 2023, 2:38 AM
iii updated this revision to Diff 516926.Apr 25 2023, 2:42 PM
  • Fixed an issue with copyRegSaveArea() overwriting shadow of caller's locals. The problem was that the kernel is compiled with "packed-stack", so register save areas may be smaller than 160 bytes. Since the kernel is compiled with "use-soft-float", it's enough (and also correct) to copy only 56 bytes. Now all kernel selftests pass.
  • Added a test for this case.
iii edited the summary of this revision. (Show Details)Apr 25 2023, 2:43 PM
This revision was landed with ongoing or failed builds.Apr 27 2023, 5:21 AM
Closed by commit rGa3e56a8792ff: [KMSAN] Enable on SystemZ (authored by iii). · Explain Why
This revision was automatically updated to reflect the committed changes.