>>On 5/3/2018 9:54 PM, Marc Zyngier wrote:
On 03/05/18 12:12, Kalra, Ashish wrote:
The reason for the problem you're seeing is probably that the
constraints are not quite right. Here, x0 is not simply clobbered, but
is actively written to in the middle of the sequence (it is at least an
early clobber). It is also, I assume, a result from the hypercall, so it
cannot simply be discarded.
It would help to get a disassembly of the function, but I'd tend to
rewrite the code as such:
extern int bar(void);
int foo(void)
{
register int w0 asm("w0");
int a, b;
a = bar();
w0 = 0x4b000000;
asm volatile("hvc #0" : "+r" (w0) :: );
b = bar();
return a - b;
}
There still is the issue of x1-x3 registers being used for local
variables and clobbering of the same across the "hvc" call.
Comparatively, the fix below works more reliably :
asm volatile("hvc #0" : "+r" (w0) :: "x1","x2","x3");
Is that because this hypercall is explicitly clobbering these registers?
or because KVM is corrupting them? If the former, fine. If the latter,
that'd be a KVM bug.
So which one is it?
It is being explicitly done by the hypercall handler:
int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
{
u32 func_id = smccc_get_function(vcpu);
u32 val = PSCI_RET_NOT_SUPPORTED;
..
..
smccc_set_retval(vcpu, val, 0, 0, 0);
}
Thanks,
Ashish