> On Sep 22, 2016, at 4:05 AM, Pete Batard <p...@akeo.ie> wrote: > > On 2016.09.22 11:06, Ard Biesheuvel wrote: >> However, there is a fundamental issue with EBC on ARM that has not >> been addressed yet, which makes EBC support problematic: >> ARM uses natural alignment for 64-bit types, which means it leaves >> gaps in the stack frame, and the thunking code has no way of dealing >> with that. > > I was hoping you would comment on this, as I believe the issue is larger than > Arm (which is why I thought the Arm patch could be integrated), since I ran > into something similar for X64 and AARCH64, with the conversion from stack to > register parameters. > > Let me start by showing a real-life example of what the current EBC > implementation does, on different architectures, if you CALLEX from EBC into > a native function call such as: > > VOID MultiParamNative( > UINT32, > UINT64, > UINT64, > UINT64, > UINT32, > UINT32, > UINT64 > ); >
Pete, Stupid question. Does adding EFIAPI fix this issue? So: VOID EFIAPI MultiParammNative( UINT32, UINT64, UINT64, UINT64, UINT32, UINT32, UINT64 ); I'm sitting next to Mike Kinney at the UEFI Forum Plug Fest and we were wondering if the calling convention stuff was mucked up on C side. Thanks, Andrew Fish > with values: > > 0x1C1C1C1C, > 0x2B2B2B2B2A2A2A2A, > 0x3B3B3B3B3A3A3A3A, > 0x4B4B4B4B4A4A4A4A, > 0x5C5C5C5C, > 0x6C6C6C6C, > 0x7B7B7B7B7A7A7A7A > > If you do that, then the parameter values seen by each Arch will be as > follows: > > IA32: > p1 = 0x1C1C1C1C > p2 = 0x2B2B2B2B2A2A2A2A > p3 = 0x3B3B3B3B3A3A3A3A > p4 = 0x4B4B4B4B4A4A4A4A > p5 = 0x5C5C5C5C > p6 = 0x6C6C6C6C > p7 = 0x7B7B7B7B7A7A7A7A > > X64: > p1 = 0x1C1C1C1C > p2 = 0x3A3A3A3A2B2B2B2B > p3 = 0x4A4A4A4A3B3B3B3B > p4 = 0x5C5C5C5C4B4B4B4B > p5 = 0x6C6C6C6C > p6 = 0x7B7B7B7B > p7 = 0x06F23E4012345678 > > ARM: > p1 = 0x1C1C1C1C > p2 = 0x3A3A3A3A2B2B2B2B > p3 = 0x4A4A4A4A3B3B3B3B > p4 = 0x5C5C5C5C4B4B4B4B > p5 = 0x6C6C6C6C > p6 = 0x7A7A7A7A > p7 = 0x446EEC467B7B7B7B > > AA64: > p1 = 0x1C1C1C1C > p2 = 0x3A3A3A3A2B2B2B2B > p3 = 0x4A4A4A4A3B3B3B3B > p4 = 0x5C5C5C5C4B4B4B4B > p5 = 0x6C6C6C6C > p6 = 0x7B7B7B7B > p7 = 0x00000000FFFFFF91 > > Note that these are real-life results gotten from a native set of drivers [1] > + EBC sample [2], specifically designed to test the above. > > So, as you can see, only IA32 currently retrieves the parameters with their > expected values. All the other platforms, and not just Arm, have an issue > with parameter retrieval. > > I too performed some analysis [3], to understand the problem, the result of > which can be summarized as follows: > > Let's say you have native protocol function: > > ProtocolCall(UINT32, UINT64, UINT64) > > to which you want to pass values: > > (0x1C1C1C1C, 0x2B2B2B2B2A2A2A2A, 0x3B3B3B3B3A3A3A3A) > > With the EBC VM, the parameters then get stacked as (little endian, CDECL and > using 32-bit longwords to represent the stack): > > +--------+ > |1C1C1C1C| > +--------+ > |2A2A2A2A| > +--------+ > |2B2B2B2B| > +--------+ > |3A3A3A3A| > +--------+ > |3B3B3B3B| > +--------+ > +????????+ > +--------+ > > Now, if you are calling into an x86_32 arch, this is no issue, as the native > call reads the parameters off the stack, and finds each one it its expected > location. > > But if, say, you are calling into native Arm, then the calling convention > dictates that the first four 32 bits parameters must be placed into Arm > registers r0-r3, rather than on the stack, and what's more, that if there > exist 64 bit parameters among the register ones, they must start with an even > register (r0 or r2). > > What this means is that, with the current EBC handling, which simply maps the > top of the stack onto registers for native CALLEX (as the VM cannot guess the > parameter signature of the function it is calling into, and therefore will > not do anything else but a blind mapping of the stack onto registers), the > native Arm function effectively gets called with the following parameter > mapping: > > +--------+ > |1C1C1C1C| -> r0 (32-bit first parameter) > +--------+ > |2A2A2A2A| -> (r1/unused, since first parameter is 32-bit) > +--------+ > |2B2B2B2B| -> r2 (lower half of 64-bit second parameter) > +--------+ > |3A3A3A3A| -> r3 (upper half of 64-bit second parameter) > +--------+ > |3B3B3B3B| -> lower half of 64-bit third parameter (stack) > +--------+ > +????????+ -> upper half of 64-bit third parameter (stack) > +--------+ > > The end result is that, the Arm call ends up with these values: > > (0x1C1C1C1C, 0x3A3A3A3A2B2B2B2B, 0x????????3B3B3B3B) > > However, while we used Arm for this example, this is not an Arm specific > issue, as x86_64 and Arm64 also expect any of the first eight parameters to a > native call, that are smaller than 64-bit, to get passed as a 64-bit > register, which means they too have the same issue as the one illustrated > above. > > Now, I'm not sure what the solution to that issue would be. I tend to agree > that, short of including a parameter signature for function calls, this > function argument marshalling issue between EBC and native will be difficult > to solve. A possible half-workaround I thought of could be to keep track of > all the PUSHes having been carried out before a CALLEX, and *assume* (or > mandate in the specs) that all the arguments were pushed individually and > that the size of the PUSH matches the desired size for a register argument, > but even that would still add a lot of complexity and be prone to breakage... > > The other solution of course is to ask EBC code developers to be aware of and > compensate for the calling convention issue, and pad the stack as required > depending on the ISA they are calling into, which is how I made my > protocol.asm sample work [4], but this is still rather inconvenient, > especially if not coding in EBC assembly, and defeats the point of trying to > write Arch independent code. > > Considering this, I'm not entirely convinced ARM EBC integration should be > held back, as the problem we are faced with is part of a larger issue that > we'll need to resolve for all archs (except IA32), and not just ARM... > > Regards, > > /Pete > > [1] https://github.com/pbatard/fasmg-ebc/tree/master/Protocol > [2] https://github.com/pbatard/fasmg-ebc/blob/master/protocol.asm > [3] https://github.com/pbatard/fasmg-ebc/blob/master/protocol.asm#L113-L177 > [4] https://github.com/pbatard/fasmg-ebc/blob/master/protocol.asm#L211-L219 > > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel