forked from Minki/linux
MIPS: KVM: Save k0 straight into VCPU structure
Currently on a guest exception the guest's k0 register is saved to the scratch temp register and the guest k1 saved to the exception base address + 0x3000 using k0 to extract the Exception Base field of the EBase register and as the base operand to the store. Both are then copied into the VCPU structure after the other general purpose registers have been saved there. This bouncing to exception base + 0x3000 is not actually necessary as the VCPU pointer can be determined and written through just as easily with only a single spare register. The VCPU pointer is already needed in k1 for saving the other GP registers, so lets save the guest k0 register straight into the VCPU structure through k1, first saving k1 into the scratch temp register instead of k0. This could potentially pave the way for having a single exception base area for use by all guests. The ehb after saving the k register to the scratch temp register is also delayed until just before it needs to be read back. Signed-off-by: James Hogan <james.hogan@imgtec.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Radim KrÄmář <rkrcmar@redhat.com> Cc: Ralf Baechle <ralf@linux-mips.org> Cc: linux-mips@linux-mips.org Cc: kvm@vger.kernel.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
1f9ca62cbc
commit
eadfb501a5
@ -347,17 +347,15 @@ void *kvm_mips_build_exception(void *addr, void *handler)
|
|||||||
memset(labels, 0, sizeof(labels));
|
memset(labels, 0, sizeof(labels));
|
||||||
memset(relocs, 0, sizeof(relocs));
|
memset(relocs, 0, sizeof(relocs));
|
||||||
|
|
||||||
/* Save guest k0 */
|
/* Save guest k1 into scratch register */
|
||||||
uasm_i_mtc0(&p, K0, scratch_tmp[0], scratch_tmp[1]);
|
uasm_i_mtc0(&p, K1, scratch_tmp[0], scratch_tmp[1]);
|
||||||
uasm_i_ehb(&p);
|
|
||||||
|
|
||||||
/* Get EBASE */
|
/* Get the VCPU pointer from the VCPU scratch register */
|
||||||
uasm_i_mfc0(&p, K0, C0_EBASE);
|
uasm_i_mfc0(&p, K1, scratch_vcpu[0], scratch_vcpu[1]);
|
||||||
/* Get rid of CPUNum */
|
uasm_i_addiu(&p, K1, K1, offsetof(struct kvm_vcpu, arch));
|
||||||
uasm_i_srl(&p, K0, K0, 10);
|
|
||||||
uasm_i_sll(&p, K0, K0, 10);
|
/* Save guest k0 into VCPU structure */
|
||||||
/* Save k1 @ offset 0x3000 */
|
UASM_i_SW(&p, K0, offsetof(struct kvm_vcpu_arch, gprs[K0]), K1);
|
||||||
UASM_i_SW(&p, K1, 0x3000, K0);
|
|
||||||
|
|
||||||
/* Branch to the common handler */
|
/* Branch to the common handler */
|
||||||
uasm_il_b(&p, &r, label_exit_common);
|
uasm_il_b(&p, &r, label_exit_common);
|
||||||
@ -395,12 +393,13 @@ void *kvm_mips_build_exit(void *addr)
|
|||||||
/*
|
/*
|
||||||
* Generic Guest exception handler. We end up here when the guest
|
* Generic Guest exception handler. We end up here when the guest
|
||||||
* does something that causes a trap to kernel mode.
|
* does something that causes a trap to kernel mode.
|
||||||
|
*
|
||||||
|
* Both k0/k1 registers will have already been saved (k0 into the vcpu
|
||||||
|
* structure, and k1 into the scratch_tmp register).
|
||||||
|
*
|
||||||
|
* The k1 register will already contain the kvm_vcpu_arch pointer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Get the VCPU pointer from the scratch register */
|
|
||||||
uasm_i_mfc0(&p, K1, scratch_vcpu[0], scratch_vcpu[1]);
|
|
||||||
uasm_i_addiu(&p, K1, K1, offsetof(struct kvm_vcpu, arch));
|
|
||||||
|
|
||||||
/* Start saving Guest context to VCPU */
|
/* Start saving Guest context to VCPU */
|
||||||
for (i = 0; i < 32; ++i) {
|
for (i = 0; i < 32; ++i) {
|
||||||
/* Guest k0/k1 saved later */
|
/* Guest k0/k1 saved later */
|
||||||
@ -416,15 +415,9 @@ void *kvm_mips_build_exit(void *addr)
|
|||||||
uasm_i_mflo(&p, T0);
|
uasm_i_mflo(&p, T0);
|
||||||
UASM_i_SW(&p, T0, offsetof(struct kvm_vcpu_arch, lo), K1);
|
UASM_i_SW(&p, T0, offsetof(struct kvm_vcpu_arch, lo), K1);
|
||||||
|
|
||||||
/* Finally save guest k0/k1 to VCPU */
|
/* Finally save guest k1 to VCPU */
|
||||||
|
uasm_i_ehb(&p);
|
||||||
uasm_i_mfc0(&p, T0, scratch_tmp[0], scratch_tmp[1]);
|
uasm_i_mfc0(&p, T0, scratch_tmp[0], scratch_tmp[1]);
|
||||||
UASM_i_SW(&p, T0, offsetof(struct kvm_vcpu_arch, gprs[K0]), K1);
|
|
||||||
|
|
||||||
/* Get GUEST k1 and save it in VCPU */
|
|
||||||
uasm_i_addiu(&p, T1, ZERO, ~0x2ff);
|
|
||||||
uasm_i_mfc0(&p, T0, C0_EBASE);
|
|
||||||
uasm_i_and(&p, T0, T0, T1);
|
|
||||||
UASM_i_LW(&p, T0, 0x3000, T0);
|
|
||||||
UASM_i_SW(&p, T0, offsetof(struct kvm_vcpu_arch, gprs[K1]), K1);
|
UASM_i_SW(&p, T0, offsetof(struct kvm_vcpu_arch, gprs[K1]), K1);
|
||||||
|
|
||||||
/* Now that context has been saved, we can use other registers */
|
/* Now that context has been saved, we can use other registers */
|
||||||
|
Loading…
Reference in New Issue
Block a user