Skip to content

Commit 11840e2

Browse files
committed
Merge tag 'for-kvmgt' of git://git.kernel.org/pub/scm/virt/kvm/kvm into drm-intel-next-queued
Paulo Bonzini writes: The three KVM patches that KVMGT needs. Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
2 parents 6a5d1db + 871b7ef commit 11840e2

File tree

16 files changed

+149
-110
lines changed

16 files changed

+149
-110
lines changed

Documentation/virtual/kvm/locking.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,17 @@ KVM Lock Overview
44
1. Acquisition Orders
55
---------------------
66

7-
(to be written)
7+
The acquisition orders for mutexes are as follows:
8+
9+
- kvm->lock is taken outside vcpu->mutex
10+
11+
- kvm->lock is taken outside kvm->slots_lock and kvm->irq_lock
12+
13+
- kvm->slots_lock is taken outside kvm->irq_lock, though acquiring
14+
them together is quite rare.
15+
16+
For spinlocks, kvm_lock is taken outside kvm->mmu_lock. Everything
17+
else is a leaf: no other lock is taken inside the critical sections.
818

919
2: Exception
1020
------------

arch/mips/include/asm/kvm_host.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,10 @@ struct kvm_vcpu_arch {
293293
/* Host KSEG0 address of the EI/DI offset */
294294
void *kseg0_commpage;
295295

296-
u32 io_gpr; /* GPR used as IO source/target */
296+
/* Resume PC after MMIO completion */
297+
unsigned long io_pc;
298+
/* GPR used as IO source/target */
299+
u32 io_gpr;
297300

298301
struct hrtimer comparecount_timer;
299302
/* Count timer control KVM register */
@@ -315,8 +318,6 @@ struct kvm_vcpu_arch {
315318
/* Bitmask of pending exceptions to be cleared */
316319
unsigned long pending_exceptions_clr;
317320

318-
u32 pending_load_cause;
319-
320321
/* Save/Restore the entryhi register when are are preempted/scheduled back in */
321322
unsigned long preempt_entryhi;
322323

arch/mips/kvm/emulate.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -790,15 +790,15 @@ enum emulation_result kvm_mips_emul_eret(struct kvm_vcpu *vcpu)
790790
struct mips_coproc *cop0 = vcpu->arch.cop0;
791791
enum emulation_result er = EMULATE_DONE;
792792

793-
if (kvm_read_c0_guest_status(cop0) & ST0_EXL) {
793+
if (kvm_read_c0_guest_status(cop0) & ST0_ERL) {
794+
kvm_clear_c0_guest_status(cop0, ST0_ERL);
795+
vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0);
796+
} else if (kvm_read_c0_guest_status(cop0) & ST0_EXL) {
794797
kvm_debug("[%#lx] ERET to %#lx\n", vcpu->arch.pc,
795798
kvm_read_c0_guest_epc(cop0));
796799
kvm_clear_c0_guest_status(cop0, ST0_EXL);
797800
vcpu->arch.pc = kvm_read_c0_guest_epc(cop0);
798801

799-
} else if (kvm_read_c0_guest_status(cop0) & ST0_ERL) {
800-
kvm_clear_c0_guest_status(cop0, ST0_ERL);
801-
vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0);
802802
} else {
803803
kvm_err("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n",
804804
vcpu->arch.pc);
@@ -1528,13 +1528,25 @@ enum emulation_result kvm_mips_emulate_load(union mips_instruction inst,
15281528
struct kvm_vcpu *vcpu)
15291529
{
15301530
enum emulation_result er = EMULATE_DO_MMIO;
1531+
unsigned long curr_pc;
15311532
u32 op, rt;
15321533
u32 bytes;
15331534

15341535
rt = inst.i_format.rt;
15351536
op = inst.i_format.opcode;
15361537

1537-
vcpu->arch.pending_load_cause = cause;
1538+
/*
1539+
* Find the resume PC now while we have safe and easy access to the
1540+
* prior branch instruction, and save it for
1541+
* kvm_mips_complete_mmio_load() to restore later.
1542+
*/
1543+
curr_pc = vcpu->arch.pc;
1544+
er = update_pc(vcpu, cause);
1545+
if (er == EMULATE_FAIL)
1546+
return er;
1547+
vcpu->arch.io_pc = vcpu->arch.pc;
1548+
vcpu->arch.pc = curr_pc;
1549+
15381550
vcpu->arch.io_gpr = rt;
15391551

15401552
switch (op) {
@@ -2494,9 +2506,8 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
24942506
goto done;
24952507
}
24962508

2497-
er = update_pc(vcpu, vcpu->arch.pending_load_cause);
2498-
if (er == EMULATE_FAIL)
2499-
return er;
2509+
/* Restore saved resume PC */
2510+
vcpu->arch.pc = vcpu->arch.io_pc;
25002511

25012512
switch (run->mmio.len) {
25022513
case 4:
@@ -2518,11 +2529,6 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
25182529
break;
25192530
}
25202531

2521-
if (vcpu->arch.pending_load_cause & CAUSEF_BD)
2522-
kvm_debug("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n",
2523-
vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr,
2524-
vcpu->mmio_needed);
2525-
25262532
done:
25272533
return er;
25282534
}

arch/mips/kvm/mips.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
426426
static void kvm_mips_check_asids(struct kvm_vcpu *vcpu)
427427
{
428428
struct mips_coproc *cop0 = vcpu->arch.cop0;
429-
int cpu = smp_processor_id();
429+
int i, cpu = smp_processor_id();
430430
unsigned int gasid;
431431

432432
/*
@@ -442,6 +442,9 @@ static void kvm_mips_check_asids(struct kvm_vcpu *vcpu)
442442
vcpu);
443443
vcpu->arch.guest_user_asid[cpu] =
444444
vcpu->arch.guest_user_mm.context.asid[cpu];
445+
for_each_possible_cpu(i)
446+
if (i != cpu)
447+
vcpu->arch.guest_user_asid[cpu] = 0;
445448
vcpu->arch.last_user_gasid = gasid;
446449
}
447450
}

arch/mips/kvm/mmu.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -260,13 +260,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
260260

261261
if ((vcpu->arch.guest_user_asid[cpu] ^ asid_cache(cpu)) &
262262
asid_version_mask(cpu)) {
263-
u32 gasid = kvm_read_c0_guest_entryhi(vcpu->arch.cop0) &
264-
KVM_ENTRYHI_ASID;
265-
266263
kvm_get_new_mmu_context(&vcpu->arch.guest_user_mm, cpu, vcpu);
267264
vcpu->arch.guest_user_asid[cpu] =
268265
vcpu->arch.guest_user_mm.context.asid[cpu];
269-
vcpu->arch.last_user_gasid = gasid;
270266
newasid++;
271267

272268
kvm_debug("[%d]: cpu_context: %#lx\n", cpu,

arch/s390/kvm/sthyi.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ static void fill_diag(struct sthyi_sctns *sctns)
315315
if (r < 0)
316316
goto out;
317317

318-
diag224_buf = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
318+
diag224_buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
319319
if (!diag224_buf || diag224(diag224_buf))
320320
goto out;
321321

@@ -378,7 +378,7 @@ static void fill_diag(struct sthyi_sctns *sctns)
378378
sctns->par.infpval1 |= PAR_WGHT_VLD;
379379

380380
out:
381-
kfree(diag224_buf);
381+
free_page((unsigned long)diag224_buf);
382382
vfree(diag204_buf);
383383
}
384384

arch/x86/include/asm/kvm_host.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,6 @@ struct kvm_x86_ops {
948948
int (*get_lpage_level)(void);
949949
bool (*rdtscp_supported)(void);
950950
bool (*invpcid_supported)(void);
951-
void (*adjust_tsc_offset_guest)(struct kvm_vcpu *vcpu, s64 adjustment);
952951

953952
void (*set_tdp_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3);
954953

@@ -958,8 +957,6 @@ struct kvm_x86_ops {
958957

959958
void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
960959

961-
u64 (*read_l1_tsc)(struct kvm_vcpu *vcpu, u64 host_tsc);
962-
963960
void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2);
964961

965962
int (*check_intercept)(struct kvm_vcpu *vcpu,

arch/x86/include/asm/kvm_page_track.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,20 @@ struct kvm_page_track_notifier_node {
2929
* @gpa: the physical address written by guest.
3030
* @new: the data was written to the address.
3131
* @bytes: the written length.
32+
* @node: this node
3233
*/
3334
void (*track_write)(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
34-
int bytes);
35+
int bytes, struct kvm_page_track_notifier_node *node);
36+
/*
37+
* It is called when memory slot is being moved or removed
38+
* users can drop write-protection for the pages in that memory slot
39+
*
40+
* @kvm: the kvm where memory slot being moved or removed
41+
* @slot: the memory slot being moved or removed
42+
* @node: this node
43+
*/
44+
void (*track_flush_slot)(struct kvm *kvm, struct kvm_memory_slot *slot,
45+
struct kvm_page_track_notifier_node *node);
3546
};
3647

3748
void kvm_page_track_init(struct kvm *kvm);
@@ -58,4 +69,5 @@ kvm_page_track_unregister_notifier(struct kvm *kvm,
5869
struct kvm_page_track_notifier_node *n);
5970
void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
6071
int bytes);
72+
void kvm_page_track_flush_slot(struct kvm *kvm, struct kvm_memory_slot *slot);
6173
#endif

arch/x86/kvm/emulate.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5045,7 +5045,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
50455045
/* Decode and fetch the destination operand: register or memory. */
50465046
rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask);
50475047

5048-
if (ctxt->rip_relative)
5048+
if (ctxt->rip_relative && likely(ctxt->memopp))
50495049
ctxt->memopp->addr.mem.ea = address_mask(ctxt,
50505050
ctxt->memopp->addr.mem.ea + ctxt->_eip);
50515051

arch/x86/kvm/mmu.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4405,7 +4405,8 @@ static u64 *get_written_sptes(struct kvm_mmu_page *sp, gpa_t gpa, int *nspte)
44054405
}
44064406

44074407
static void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
4408-
const u8 *new, int bytes)
4408+
const u8 *new, int bytes,
4409+
struct kvm_page_track_notifier_node *node)
44094410
{
44104411
gfn_t gfn = gpa >> PAGE_SHIFT;
44114412
struct kvm_mmu_page *sp;
@@ -4617,11 +4618,19 @@ void kvm_mmu_setup(struct kvm_vcpu *vcpu)
46174618
init_kvm_mmu(vcpu);
46184619
}
46194620

4621+
static void kvm_mmu_invalidate_zap_pages_in_memslot(struct kvm *kvm,
4622+
struct kvm_memory_slot *slot,
4623+
struct kvm_page_track_notifier_node *node)
4624+
{
4625+
kvm_mmu_invalidate_zap_all_pages(kvm);
4626+
}
4627+
46204628
void kvm_mmu_init_vm(struct kvm *kvm)
46214629
{
46224630
struct kvm_page_track_notifier_node *node = &kvm->arch.mmu_sp_tracker;
46234631

46244632
node->track_write = kvm_mmu_pte_write;
4633+
node->track_flush_slot = kvm_mmu_invalidate_zap_pages_in_memslot;
46254634
kvm_page_track_register_notifier(kvm, node);
46264635
}
46274636

arch/x86/kvm/page_track.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ void kvm_slot_page_track_add_page(struct kvm *kvm,
106106
if (kvm_mmu_slot_gfn_write_protect(kvm, slot, gfn))
107107
kvm_flush_remote_tlbs(kvm);
108108
}
109+
EXPORT_SYMBOL_GPL(kvm_slot_page_track_add_page);
109110

110111
/*
111112
* remove the guest page from the tracking pool which stops the interception
@@ -135,6 +136,7 @@ void kvm_slot_page_track_remove_page(struct kvm *kvm,
135136
*/
136137
kvm_mmu_gfn_allow_lpage(slot, gfn);
137138
}
139+
EXPORT_SYMBOL_GPL(kvm_slot_page_track_remove_page);
138140

139141
/*
140142
* check if the corresponding access on the specified guest page is tracked.
@@ -181,6 +183,7 @@ kvm_page_track_register_notifier(struct kvm *kvm,
181183
hlist_add_head_rcu(&n->node, &head->track_notifier_list);
182184
spin_unlock(&kvm->mmu_lock);
183185
}
186+
EXPORT_SYMBOL_GPL(kvm_page_track_register_notifier);
184187

185188
/*
186189
* stop receiving the event interception. It is the opposed operation of
@@ -199,6 +202,7 @@ kvm_page_track_unregister_notifier(struct kvm *kvm,
199202
spin_unlock(&kvm->mmu_lock);
200203
synchronize_srcu(&head->track_srcu);
201204
}
205+
EXPORT_SYMBOL_GPL(kvm_page_track_unregister_notifier);
202206

203207
/*
204208
* Notify the node that write access is intercepted and write emulation is
@@ -222,6 +226,31 @@ void kvm_page_track_write(struct kvm_vcpu *vcpu, gpa_t gpa, const u8 *new,
222226
idx = srcu_read_lock(&head->track_srcu);
223227
hlist_for_each_entry_rcu(n, &head->track_notifier_list, node)
224228
if (n->track_write)
225-
n->track_write(vcpu, gpa, new, bytes);
229+
n->track_write(vcpu, gpa, new, bytes, n);
230+
srcu_read_unlock(&head->track_srcu, idx);
231+
}
232+
233+
/*
234+
* Notify the node that memory slot is being removed or moved so that it can
235+
* drop write-protection for the pages in the memory slot.
236+
*
237+
* The node should figure out it has any write-protected pages in this slot
238+
* by itself.
239+
*/
240+
void kvm_page_track_flush_slot(struct kvm *kvm, struct kvm_memory_slot *slot)
241+
{
242+
struct kvm_page_track_notifier_head *head;
243+
struct kvm_page_track_notifier_node *n;
244+
int idx;
245+
246+
head = &kvm->arch.track_notifier_head;
247+
248+
if (hlist_empty(&head->track_notifier_list))
249+
return;
250+
251+
idx = srcu_read_lock(&head->track_srcu);
252+
hlist_for_each_entry_rcu(n, &head->track_notifier_list, node)
253+
if (n->track_flush_slot)
254+
n->track_flush_slot(kvm, slot, n);
226255
srcu_read_unlock(&head->track_srcu, idx);
227256
}

arch/x86/kvm/svm.c

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,21 +1138,6 @@ static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
11381138
mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
11391139
}
11401140

1141-
static void svm_adjust_tsc_offset_guest(struct kvm_vcpu *vcpu, s64 adjustment)
1142-
{
1143-
struct vcpu_svm *svm = to_svm(vcpu);
1144-
1145-
svm->vmcb->control.tsc_offset += adjustment;
1146-
if (is_guest_mode(vcpu))
1147-
svm->nested.hsave->control.tsc_offset += adjustment;
1148-
else
1149-
trace_kvm_write_tsc_offset(vcpu->vcpu_id,
1150-
svm->vmcb->control.tsc_offset - adjustment,
1151-
svm->vmcb->control.tsc_offset);
1152-
1153-
mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
1154-
}
1155-
11561141
static void avic_init_vmcb(struct vcpu_svm *svm)
11571142
{
11581143
struct vmcb *vmcb = svm->vmcb;
@@ -3449,12 +3434,6 @@ static int cr8_write_interception(struct vcpu_svm *svm)
34493434
return 0;
34503435
}
34513436

3452-
static u64 svm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc)
3453-
{
3454-
struct vmcb *vmcb = get_host_vmcb(to_svm(vcpu));
3455-
return vmcb->control.tsc_offset + host_tsc;
3456-
}
3457-
34583437
static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
34593438
{
34603439
struct vcpu_svm *svm = to_svm(vcpu);
@@ -5422,8 +5401,6 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
54225401
.has_wbinvd_exit = svm_has_wbinvd_exit,
54235402

54245403
.write_tsc_offset = svm_write_tsc_offset,
5425-
.adjust_tsc_offset_guest = svm_adjust_tsc_offset_guest,
5426-
.read_l1_tsc = svm_read_l1_tsc,
54275404

54285405
.set_tdp_cr3 = set_tdp_cr3,
54295406

0 commit comments

Comments
 (0)