lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 11 May 2021 07:39:33 -0700
From:   Dave Hansen <dave.hansen@...el.com>
To:     "Kuppuswamy, Sathyanarayanan" 
        <sathyanarayanan.kuppuswamy@...ux.intel.com>,
        Dan Williams <dan.j.williams@...el.com>
Cc:     Andi Kleen <ak@...ux.intel.com>,
        Peter Zijlstra <peterz@...radead.org>,
        Andy Lutomirski <luto@...nel.org>,
        Tony Luck <tony.luck@...el.com>,
        Kirill Shutemov <kirill.shutemov@...ux.intel.com>,
        Kuppuswamy Sathyanarayanan <knsathya@...nel.org>,
        Raj Ashok <ashok.raj@...el.com>,
        Sean Christopherson <seanjc@...gle.com>,
        Linux Kernel Mailing List <linux-kernel@...r.kernel.org>
Subject: Re: [RFC v2 14/32] x86/tdx: Handle port I/O

On 5/10/21 7:29 PM, Kuppuswamy, Sathyanarayanan wrote:
> On 5/10/21 6:07 PM, Dan Williams wrote:
>> On Mon, May 10, 2021 at 5:30 PM Kuppuswamy, Sathyanarayanan
>> <sathyanarayanan.kuppuswamy@...ux.intel.com> wrote:
>> [..]
>>> It is mainly used by functions like
>>> __tdx_hypercall(),__tdx_hypercall_vendor_kvm()
>>> and tdx_in{b,w,l}.
>>>
>>> u64 __tdx_hypercall(u64 fn, u64 r12, u64 r13, u64 r14, u64 r15,
>>>                       struct tdx_hypercall_output *out);
>>> u64 __tdx_hypercall_vendor_kvm(u64 fn, u64 r12, u64 r13, u64 r14,
>>>                                  u64 r15, struct tdx_hypercall_output
>>> *out);
>>>
>>> struct tdx_hypercall_output {
>>>           u64 r11;
>>>           u64 r12;
>>>           u64 r13;
>>>           u64 r14;
>>>           u64 r15;
>>> };
>>
>> Why is this by register name and not something like:
>>
>> struct tdx_hypercall_payload {
>>    u64 data[5];
>> };
>>
>> ...because the code in this patch is reading the payload out of a
>> stack relative offset, not r11.
> 
> Since this patch allocates this memory in ASM code, we read it via
> offset. If you see other use cases in tdx.c, you will notice the use
> of register names.

To what you do you refer by "this patch allocates this memory in ASM
code"?  Could you point to the specific ASM code that "allocates memory"?

Dan I'll try to answer your question.  TDX has both a "hypercall"
interface for guests to call into hosts and a "seamcall" interface where
guests or hosts can talk to the TDX/SEAM module.

Both of these represent an ABI which _resembles_ a system call ABI.
Values are placed in registers, including a "function" register which is
very similar to a the system call number we place in RAX.

*But* those ABIs was actually designed to (IIRC) resemble the
Windows/Microsoft ABI, not the Linux ABI.  So the register conventions
are unfamiliar.  There is assembly code to convert between the ELF
function call ABI and the TDX ABIs.

For instance, if you are in C code and you call:

	__tdx_hypercall_vendor_kvm(u64 fn, u64 r12, ...

The value for "fn" will be placed in RAX and "r12" will be placed in RDI
for the function call itself.  The assembly code will, for instance,
take the "r12" *VARIABLE* and ensure it gets into the R12 *REGISTER* for
the hypercall.

The same thing happens on the output side.  The TDX ABIs specify
"return" values in certain registers (r11-r15).  However, those
registers are not preserved in our function return ABI.  So, they must
be stashed off in memory into a place where the caller can retrieve them.

Rather than being unstructured "data[]", the value in
tdx_hypercall_output->r11 was actually in register R11 at some point.
If you look at the spec, you can see the functions that use R11.

Let's say there's a hypercall to check for whether puppies are cute.
Here's the kernel side:

bool tdx_hypercall_puppies_are_cute()
{
	struct tdx_hypercall_output out;
	u64 ret;

	ret = __tdx_hypercall_vendor_kvm(HOST_LIKES_PUPPIES, ..., &out);

	/* Did the hypercall even succeed? */
	if (ret != SUCCESS)
		return -EINVAL;

	if (out->r11 == TDX_WHATEVER_CUTE_BIT)
		return true;

	// Nope, I guess puppies are not cute
	return false;
}

The spec would actually say, "Blah blah, puppies are cute if
TDX_WHATEVER_CUTE_BIT is set in r11".  So, this whole setup actually
results in really nice C code that you can sit side-by-side with the
spec and see if they agree.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ