Re: [PATCH v2 04/17] perf: x86/ds: Handle guest PEBS overflow PMI and inject it to guest

From: Xu, Like
Date: Mon Nov 30 2020 - 20:26:36 EST


Hi Peter,

On 2020/11/30 18:49, Peter Zijlstra wrote:
On Fri, Nov 27, 2020 at 10:14:49AM +0800, Xu, Like wrote:

OK, but the code here wanted to inspect the guest DS from the host. It
states this is somehow complicated/expensive. But surely we can at the
very least map the first guest DS page somewhere so we can at least
access the control bits without too much magic.
We note that the SDM has a contiguous present memory mapping
assumption about the DS save area and the PEBS buffer area.

Therefore, we revisit your suggestion here and move it a bit forward:

When the PEBS is enabled, KVM will cache the following values:
- gva ds_area (kvm msr trap)
- hva1 for "gva ds_area" (walk guest page table)
- hva2 for "gva pebs_buffer_base" via hva1 (walk guest page table)
What this [gh]va? Guest/Host Virtual Address? I think you're assuming I
know about all this virt crap,.. I don't.
Oh, my bad and let me add it:

gva: guest virtual address
gpa: guest physical address
gfn: guest frame number
hva: host virtual adderss
hpa: host physical address

In the KVM, we get hva from gva in the following way:

gpa = kvm_mmu_gva_to_gpa_system(vcpu, gva, NULL);
gfn = gpa >> PAGE_SHIFT;
slot = gfn_to_memslot(kvm, gfn);
hva = gfn_to_hva_memslot_prot(slot, gfn, NULL);


if the "gva ds_area" cache hits,
what?
Sorry, it looks a misuse of terminology.

I mean KVM will save the last used "gva ds_area" value and its hva in the extra fields,
if the "gva ds_area" does not change this time, we will not walk the guest page table
to get its hva again.

I think it's the main point in your suggestion, and I try to elaborate it.
- access PEBS "interrupt threshold" and "Counter Reset[]" via hva1
- get "gva2 pebs_buffer_base" via __copy_from_user(hva1)
But you already had hva2, so what's the point?
hva1 is for for "gva ds_area"
hva2 is for "gva pebs_buffer_base"

The point is before using the last save hva2, we need to
make sure that "gva pebs_buffer_base" is not changed to avoid
that some malicious drivers may change it without changing ds_area.


if the "gva2 pebs_buffer_base" cache hits,
What?

- we get "gva2 pebs_index" via __copy_from_user(hva2),
pebs_index is in ds_are, which would be hva1
Yes, we get "gva2 pebs_index" via __copy_from_user(hva1).

- rewrite the guest PEBS records via hva2 and pebs_index

If any cache misses, setup the cache values via walking tables again.

I wonder if you would agree with this optimization idea,
we look forward to your confirmation for the next step.
I'm utterly confused. I really can't follow.
Generally, KVM will save hva1 (gva1 ds_area) and hva2 (for gva2 pebs_buffer_base)
in the first round of the guest page table walking and reuse them
if they're not changed in subsequent use.

I think this approach is feasible, and please complain if you are still confused or disagree.

Thanks,
Like Xu