[RFC PATCH v4 0/2] ARM/ARM64 KVM dealing with coproc registers in BE code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Marc, Christoffer,

The most controversial piece of my BE KVM series is patches
that deals with coproc registers byteswaps, especially in V7
case. Here I send my lasted proposed version as RFC, hopping
to get more discussion on the subject. In the following this
cover letter patches I did address some of Christoffer's
suggestions but still not completely.

Approach 1
----------

That is the one I try to pursue and current patches are about
it. With current scheme which I try to change we have two main
issues:

1) current reg_from_user takes 'void *' and can take pointer to
host u64 value or u32 value as well as register size could 8 or
4 bytes. In case of BE, and register size 4 bytes, it is
impossible to differentiate between case where pointer to
u32 is passed to function or pointer to u64 passed to function.
In case of u32 pointer 4 bytes should be copied to val address
itself but in case of u64 pointer in order to update low word
of u64 value 4 bytes should be copied at 'val + 4' address.
To fix it strong typed versions depending on kernel target type 
of functions are introduced:
    reg_from_user_to_u32 and reg_to_user_from_u32
    reg_from_user_to_u64 and reg_to_user_from_u64
It seems to me that Christoffer is fine with this approach.
Marc, from your comment it was not clear whether you against
this approach or needed clarification why reg_xxx_[u32|u64]
function were introduced.

2) Size of target kernel variable u32 and u64 may mismatch 
size of requested register. We have two sub-cases here.
  a) 4 bytes register could be read from kernel u64
  b) 8 byte register (LPAE related TTBR, etc) could be
  read from array of two u32 values.

It seems that for case 2a) we have only couple cases in 
get_invariant_cp15 and set_invariant_cp15 functions. I
followed Christoffer's suggestion, I disallowed use of
4 bytes register size along with u64 kernel target and
changed get_invariant_cp15 and set_invariant_cp15 to
deals with different register sizes calling _u64 variant
of _u32 variant separately. I don't know how to clean
up 2b) case I left it alone.

Approach 2
----------

Alex Graf suggested to move in this direction. I looked
at it and I don't see how to apply it. But for completeness
sake here is my observation. 

PPC deals with similar issues already. But PPC coproc 
handling code is structured fundamentally in different
way. If in ARM access of userspace is pushed to leaf
functions in PPC userspace value is read or written by
top level function. Guts of coproc handling code deal
with kvmppc_one_reg union that is defined like this:

union kvmppc_one_reg {
	u32	wval;
	u64	dval;
	vector128 vval;
	u64	vsxval[2];
	struct {
		u64	addr;
		u64	length;
	}	vpaval;
};

But note that besides wval and daval, there are PPC specific
values like vval, vsxval, vpaval ...

kvmppc_one_reg union is passed to different functions that
deal with different classes of coproc values. Those functions
use get_reg_val and set_reg_val macros which are
defined like this:

#define get_reg_val(id, reg)	({		\
	union kvmppc_one_reg __u;		\
	switch (one_reg_size(id)) {		\
	case 4: __u.wval = (reg); break;	\
	case 8: __u.dval = (reg); break;	\
	default: BUG();				\
	}					\
	__u;					\
})

#define set_reg_val(id, val)	({		\
	u64 __v;				\
	switch (one_reg_size(id)) {		\
	case 4: __v = (val).wval; break;	\
	case 8: __v = (val).dval; break;	\
	default: BUG();				\
	}					\
	__v;					\
})

(On the side: note BUG() call with sizes other 4 or 8;
it seems that this code has similar issue that Marc
caught in one of my diffs: BUG_ON call. It seems to
me that userspace can craft special reg id that could
trigger this BUG() call)

My main problem with this approach is that we
would need to rework where ARM KVM coproc handling
functions access userspace. IMHO it is a lot of 
changes. In fact it will be way more changes than
in my diff because in ARM KVM code there are cases
where put_user/get_user is used in leaf functions
instead of reg_from_user function. Also it is not
clear how to handle 2b) case in above Approach 1.
Also code sharing would not be that great. Unless
I am missing something It looks like only get_reg_val
set_reg_val could be reused. And it is not clear
how to define common between ARM and PPC kvm_one_reg
union.

Also for V8 case as per following patch (ARM64: KVM: 
set and get of sys registers in BE case) we don't
have big issue, because all registers are 64 bit.
But for consistency sake it will need to be reworked
too.

I hope you would agree that benefits of following
on this approach are not that great. Please let me
know if you think otherwise.

Thanks,
Victor

Victor Kamensky (2):
  ARM: KVM: one_reg coproc set and get BE fixes
  ARM64: KVM: set and get of sys registers in BE case

 arch/arm/kvm/coproc.c     | 111 +++++++++++++++++++++++++++++++++++-----------
 arch/arm64/kvm/sys_regs.c |  21 ++++++---
 2 files changed, 99 insertions(+), 33 deletions(-)

-- 
1.8.1.4

_______________________________________________
kvmarm mailing list
kvmarm@xxxxxxxxxxxxxxxxxxxxx
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm




[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux