Skip to content

Commit 42aa12e

Browse files
James Hoganbonzini
authored andcommitted
MIPS: KVM: Move commpage so 0x0 is unmapped
The comm page which is mapped into the guest kernel address space at 0x0 has the unfortunate side effect of allowing guest kernel NULL pointer dereferences to succeed. The only constraint on this address is that it must be within 32KiB of 0x0, so that single lw/sw instructions (which have 16-bit signed offset fields) can be used to access it, using the zero register as a base. So lets move the comm page as high as possible within that constraint so that 0x0 can be left unmapped, at least for page sizes < 32KiB. 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>
1 parent 0510870 commit 42aa12e

File tree

4 files changed

+20
-14
lines changed

4 files changed

+20
-14
lines changed

arch/mips/include/asm/kvm_host.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,14 @@
7474

7575

7676

77-
/* Special address that contains the comm page, used for reducing # of traps */
78-
#define KVM_GUEST_COMMPAGE_ADDR 0x0
77+
/*
78+
* Special address that contains the comm page, used for reducing # of traps
79+
* This needs to be within 32Kb of 0x0 (so the zero register can be used), but
80+
* preferably not at 0x0 so that most kernel NULL pointer dereferences can be
81+
* caught.
82+
*/
83+
#define KVM_GUEST_COMMPAGE_ADDR ((PAGE_SIZE > 0x8000) ? 0 : \
84+
(0x8000 - PAGE_SIZE))
7985

8086
#define KVM_GUEST_KERNEL_MODE(vcpu) ((kvm_read_c0_guest_status(vcpu->arch.cop0) & (ST0_EXL | ST0_ERL)) || \
8187
((kvm_read_c0_guest_status(vcpu->arch.cop0) & KSU_USER) == 0))

arch/mips/kvm/commpage.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* for more details.
55
*
66
* commpage, currently used for Virtual COP0 registers.
7-
* Mapped into the guest kernel @ 0x0.
7+
* Mapped into the guest kernel @ KVM_GUEST_COMMPAGE_ADDR.
88
*
99
* Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
1010
* Authors: Sanjay Lal <sanjayl@kymasys.com>

arch/mips/kvm/dyntrans.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ int kvm_mips_trans_mfc0(union mips_instruction inst, u32 *opc,
9393
} else {
9494
mfc0_inst.i_format.opcode = lw_op;
9595
mfc0_inst.i_format.rt = inst.c0r_format.rt;
96-
mfc0_inst.i_format.simmediate =
96+
mfc0_inst.i_format.simmediate = KVM_GUEST_COMMPAGE_ADDR |
9797
offsetof(struct kvm_mips_commpage, cop0.reg[rd][sel]);
9898
}
9999

@@ -111,7 +111,7 @@ int kvm_mips_trans_mtc0(union mips_instruction inst, u32 *opc,
111111

112112
mtc0_inst.i_format.opcode = sw_op;
113113
mtc0_inst.i_format.rt = inst.c0r_format.rt;
114-
mtc0_inst.i_format.simmediate =
114+
mtc0_inst.i_format.simmediate = KVM_GUEST_COMMPAGE_ADDR |
115115
offsetof(struct kvm_mips_commpage, cop0.reg[rd][sel]);
116116

117117
return kvm_mips_trans_replace(vcpu, opc, mtc0_inst);

arch/mips/kvm/tlb.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -171,23 +171,23 @@ EXPORT_SYMBOL_GPL(kvm_mips_host_tlb_write);
171171
int kvm_mips_handle_commpage_tlb_fault(unsigned long badvaddr,
172172
struct kvm_vcpu *vcpu)
173173
{
174-
kvm_pfn_t pfn0, pfn1;
174+
kvm_pfn_t pfn;
175175
unsigned long flags, old_entryhi = 0, vaddr = 0;
176-
unsigned long entrylo0 = 0, entrylo1 = 0;
176+
unsigned long entrylo[2] = { 0, 0 };
177+
unsigned int pair_idx;
177178

178-
pfn0 = CPHYSADDR(vcpu->arch.kseg0_commpage) >> PAGE_SHIFT;
179-
pfn1 = 0;
180-
entrylo0 = mips3_paddr_to_tlbpfn(pfn0 << PAGE_SHIFT) |
181-
(0x3 << ENTRYLO_C_SHIFT) | ENTRYLO_D | ENTRYLO_V;
182-
entrylo1 = 0;
179+
pfn = CPHYSADDR(vcpu->arch.kseg0_commpage) >> PAGE_SHIFT;
180+
pair_idx = (badvaddr >> PAGE_SHIFT) & 1;
181+
entrylo[pair_idx] = mips3_paddr_to_tlbpfn(pfn << PAGE_SHIFT) |
182+
(0x3 << ENTRYLO_C_SHIFT) | ENTRYLO_D | ENTRYLO_V;
183183

184184
local_irq_save(flags);
185185

186186
old_entryhi = read_c0_entryhi();
187187
vaddr = badvaddr & (PAGE_MASK << 1);
188188
write_c0_entryhi(vaddr | kvm_mips_get_kernel_asid(vcpu));
189-
write_c0_entrylo0(entrylo0);
190-
write_c0_entrylo1(entrylo1);
189+
write_c0_entrylo0(entrylo[0]);
190+
write_c0_entrylo1(entrylo[1]);
191191
write_c0_index(kvm_mips_get_commpage_asid(vcpu));
192192
mtc0_tlbw_hazard();
193193
tlb_write_indexed();

0 commit comments

Comments
 (0)