* [Qemu-devel] Address translation - virt->phys->ram
@ 2010-02-22 13:59 Ian Molton
2010-02-22 14:35 ` Anthony Liguori
0 siblings, 1 reply; 9+ messages in thread
From: Ian Molton @ 2010-02-22 13:59 UTC (permalink / raw)
To: qemu-devel
Hi folks,
I've been updating some old patches which make use of a function to
translate guest virtual addresses into pointers into the guest RAM.
As I understand it qemu has guest virtual and physical addresses, the
latter of which map somehow to host ram addresses.
The function which the code had been using appears not to work under
kvm, which leads me to think that qemu doesnt emulate the MMU (or at
least not in the same manner) when it is using kvm as opposed to pure
emulation.
If I turn off kvm, the patch works, albeit slowly. If I enable it, the
code takes the path which looks for the magic value (below).
Is there a 'proper' way to translate guest virtual addresses into host
RAM addresses?
Here is the code:-
static /*inline*/ void *get_phys_mem_addr(CPUState *env, target_ulong addr)
{
int mmu_idx;
int index;
int i;
index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
mmu_idx = cpu_mmu_index(env);
if (__builtin_expect
(env->tlb_table[mmu_idx][index].addr_code !=
(addr & TARGET_PAGE_MASK), 0)) {
target_ulong ret = cpu_get_phys_page_debug((CPUState *) env, addr);
if (ret == -1) {
fprintf(stderr,
"not in phys mem " TARGET_FMT_lx "(" TARGET_FMT_lx " "
TARGET_FMT_lx ")\n", addr,
env->tlb_table[mmu_idx][index].addr_code,
addr & TARGET_PAGE_MASK);
fprintf(stderr, "cpu_x86_handle_mmu_fault = %d\n",
cpu_x86_handle_mmu_fault((CPUState *) env, addr, 0,
mmu_idx, 1));
return NULL;
} else {
if (ret + TARGET_PAGE_SIZE <= ram_size) {
return qemu_get_ram_ptr((ret + (((target_ulong) addr) &
(TARGET_PAGE_SIZE - 1))));
} else {
fprintf(stderr,
"cpu_get_phys_page_debug(env, " TARGET_FMT_lx ")
== "
TARGET_FMT_lx "\n", addr, ret);
fprintf(stderr,
"ram_size= " TARGET_FMT_lx "\n", ret,
(target_ulong) ram_size);
for(i = 0 ; i < ram_size-10 ; i++) {
char *ptr = qemu_get_ram_ptr(i);
if(!strncmp("magic_string", ptr, 10)) {
fprintf(stderr, "found magic_string at: %lx
%lx\n", i, ptr);
break;
}
}
return qemu_get_ram_ptr(i-128); //Evil horrible hack
}
}
} else
return (void *) addr + env->tlb_table[mmu_idx][index].addend;
}
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] Address translation - virt->phys->ram
2010-02-22 13:59 [Qemu-devel] Address translation - virt->phys->ram Ian Molton
@ 2010-02-22 14:35 ` Anthony Liguori
2010-02-22 16:46 ` Ian Molton
0 siblings, 1 reply; 9+ messages in thread
From: Anthony Liguori @ 2010-02-22 14:35 UTC (permalink / raw)
To: Ian Molton; +Cc: qemu-devel
On 02/22/2010 07:59 AM, Ian Molton wrote:
> Hi folks,
>
> I've been updating some old patches which make use of a function to
> translate guest virtual addresses into pointers into the guest RAM.
>
> As I understand it qemu has guest virtual and physical addresses, the
> latter of which map somehow to host ram addresses.
>
> The function which the code had been using appears not to work under
> kvm, which leads me to think that qemu doesnt emulate the MMU (or at
> least not in the same manner) when it is using kvm as opposed to pure
> emulation.
>
> If I turn off kvm, the patch works, albeit slowly. If I enable it, the
> code takes the path which looks for the magic value (below).
>
> Is there a 'proper' way to translate guest virtual addresses into host
> RAM addresses?
>
cpu_physical_memory_map().
But this function has some subtle characteristics. It may return a
bounce buffer if you attempt to map MMIO memory. There is a limited
pool of bounce buffers available so it may return NULL in the event that
it cannot allocate a bounce buffer.
It may also return a partial result if you're attempting to map a region
that straddles multiple memory slots.
Regards,
Anthony Liguori
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] Address translation - virt->phys->ram
2010-02-22 14:35 ` Anthony Liguori
@ 2010-02-22 16:46 ` Ian Molton
2010-02-22 16:52 ` Anthony Liguori
0 siblings, 1 reply; 9+ messages in thread
From: Ian Molton @ 2010-02-22 16:46 UTC (permalink / raw)
To: Anthony Liguori; +Cc: qemu-devel
Anthony Liguori wrote:
> cpu_physical_memory_map().
>
> But this function has some subtle characteristics. It may return a
> bounce buffer if you attempt to map MMIO memory. There is a limited
> pool of bounce buffers available so it may return NULL in the event that
> it cannot allocate a bounce buffer.
>
> It may also return a partial result if you're attempting to map a region
> that straddles multiple memory slots.
Thanks. I had found this, but was unsure as to wether it was quite what
I wanted. (also is it possible to tell when it has (eg.) allocated a
bounce buffer?)
Basically, I need to get buffer(s) from guest userspace into the hosts
address space. The buffers are virtually contiguous but likely
physically discontiguous. They are allocated with malloc() and theres
nothing I can do about that.
The obvious but slow solution would be to copy all the buffers into nice
virtio-based scatter/gather buffers and feed them to the host that way,
however its not fast enough.
Right now I have a little driver I have written that allows a buffer to
be mmap()ed by the guest userspace, and this is pushed to the host via
virtio s/g io when the guest calls fsync(). This buffer contains the
data that must be passed to the host, however this data may often
contain pointers to (that is, userspace virtual addresses of) buffers of
unknown sizes which the host also needs to access. These buffers are
what I need to read from the guests RAM.
The buffers will likely remain active across multiple different calls to
the host so their pages will need to be available. As the calls always
happen when that specific process is active, I'd guess the worst we need
to do is generate a page fault to unswap the page(s). Can that be caused
by qemu (under kvm)?
It seems that cpu_physical_memory_map() deals with physically contiguous
areas of guest address space. I need to get a host-side mapping of a
*virtually* contiguous (possibly physically discontiguous) set of guest
pages. If this can be done, it'd mean direct transfer of data from guest
application to host shared library, which would be a major win.
-Ian
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] Address translation - virt->phys->ram
2010-02-22 16:46 ` Ian Molton
@ 2010-02-22 16:52 ` Anthony Liguori
2010-02-22 17:47 ` Ian Molton
0 siblings, 1 reply; 9+ messages in thread
From: Anthony Liguori @ 2010-02-22 16:52 UTC (permalink / raw)
To: Ian Molton; +Cc: qemu-devel
On 02/22/2010 10:46 AM, Ian Molton wrote:
> Anthony Liguori wrote:
>
>
>> cpu_physical_memory_map().
>>
>> But this function has some subtle characteristics. It may return a
>> bounce buffer if you attempt to map MMIO memory. There is a limited
>> pool of bounce buffers available so it may return NULL in the event that
>> it cannot allocate a bounce buffer.
>>
>> It may also return a partial result if you're attempting to map a region
>> that straddles multiple memory slots.
>>
> Thanks. I had found this, but was unsure as to wether it was quite what
> I wanted. (also is it possible to tell when it has (eg.) allocated a
> bounce buffer?)
>
> Basically, I need to get buffer(s) from guest userspace into the hosts
> address space. The buffers are virtually contiguous but likely
> physically discontiguous. They are allocated with malloc() and theres
> nothing I can do about that.
>
> The obvious but slow solution would be to copy all the buffers into nice
> virtio-based scatter/gather buffers and feed them to the host that way,
> however its not fast enough.
>
Why is this slow?
Regards,
Anthony Liguori
> Right now I have a little driver I have written that allows a buffer to
> be mmap()ed by the guest userspace, and this is pushed to the host via
> virtio s/g io when the guest calls fsync(). This buffer contains the
> data that must be passed to the host, however this data may often
> contain pointers to (that is, userspace virtual addresses of) buffers of
> unknown sizes which the host also needs to access. These buffers are
> what I need to read from the guests RAM.
>
> The buffers will likely remain active across multiple different calls to
> the host so their pages will need to be available. As the calls always
> happen when that specific process is active, I'd guess the worst we need
> to do is generate a page fault to unswap the page(s). Can that be caused
> by qemu (under kvm)?
>
> It seems that cpu_physical_memory_map() deals with physically contiguous
> areas of guest address space. I need to get a host-side mapping of a
> *virtually* contiguous (possibly physically discontiguous) set of guest
> pages. If this can be done, it'd mean direct transfer of data from guest
> application to host shared library, which would be a major win.
>
> -Ian
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] Address translation - virt->phys->ram
2010-02-22 16:52 ` Anthony Liguori
@ 2010-02-22 17:47 ` Ian Molton
2010-02-22 18:56 ` Alexander Graf
2010-02-23 16:21 ` Anthony Liguori
0 siblings, 2 replies; 9+ messages in thread
From: Ian Molton @ 2010-02-22 17:47 UTC (permalink / raw)
To: Anthony Liguori; +Cc: qemu-devel
Anthony Liguori wrote:
> On 02/22/2010 10:46 AM, Ian Molton wrote:
>> Anthony Liguori wrote:
>>
>>
>>> cpu_physical_memory_map().
>>>
>>> But this function has some subtle characteristics. It may return a
>>> bounce buffer if you attempt to map MMIO memory. There is a limited
>>> pool of bounce buffers available so it may return NULL in the event that
>>> it cannot allocate a bounce buffer.
>>>
>>> It may also return a partial result if you're attempting to map a region
>>> that straddles multiple memory slots.
>>>
>> Thanks. I had found this, but was unsure as to wether it was quite what
>> I wanted. (also is it possible to tell when it has (eg.) allocated a
>> bounce buffer?)
>>
>> Basically, I need to get buffer(s) from guest userspace into the hosts
>> address space. The buffers are virtually contiguous but likely
>> physically discontiguous. They are allocated with malloc() and theres
>> nothing I can do about that.
>>
>> The obvious but slow solution would be to copy all the buffers into nice
>> virtio-based scatter/gather buffers and feed them to the host that way,
>> however its not fast enough.
>>
>
> Why is this slow?
Because the buffers will all have to be copied. So far, switching from
abusing an instruction to interrupt qemu to using virtio has incurred a
roughly 5x slowdown. I'd guess much of this is down to the fact we have
to switch to kernel-mode on the guest and back again for every single GL
call...
If I can establish some kind of stable guest_virt->phys->host_virt
mapping, many of the problems will just 'go away'. a way to interrupt
qemu from user-mode on the guest without involving the guest kernel
would be quite awesome also (theres really nothing we want the kernel to
actually /do/ here, it just adds overhead).
-Ian
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] Address translation - virt->phys->ram
2010-02-22 17:47 ` Ian Molton
@ 2010-02-22 18:56 ` Alexander Graf
2010-02-23 15:46 ` Ian Molton
2010-02-23 16:21 ` Anthony Liguori
1 sibling, 1 reply; 9+ messages in thread
From: Alexander Graf @ 2010-02-22 18:56 UTC (permalink / raw)
To: Ian Molton; +Cc: cam, qemu-devel
Ian Molton wrote:
> Anthony Liguori wrote:
>
>> On 02/22/2010 10:46 AM, Ian Molton wrote:
>>
>>> Anthony Liguori wrote:
>>>
>>>
>>>
>>>> cpu_physical_memory_map().
>>>>
>>>> But this function has some subtle characteristics. It may return a
>>>> bounce buffer if you attempt to map MMIO memory. There is a limited
>>>> pool of bounce buffers available so it may return NULL in the event that
>>>> it cannot allocate a bounce buffer.
>>>>
>>>> It may also return a partial result if you're attempting to map a region
>>>> that straddles multiple memory slots.
>>>>
>>>>
>>> Thanks. I had found this, but was unsure as to wether it was quite what
>>> I wanted. (also is it possible to tell when it has (eg.) allocated a
>>> bounce buffer?)
>>>
>>> Basically, I need to get buffer(s) from guest userspace into the hosts
>>> address space. The buffers are virtually contiguous but likely
>>> physically discontiguous. They are allocated with malloc() and theres
>>> nothing I can do about that.
>>>
>>> The obvious but slow solution would be to copy all the buffers into nice
>>> virtio-based scatter/gather buffers and feed them to the host that way,
>>> however its not fast enough.
>>>
>>>
>> Why is this slow?
>>
>
> Because the buffers will all have to be copied. So far, switching from
> abusing an instruction to interrupt qemu to using virtio has incurred a
> roughly 5x slowdown. I'd guess much of this is down to the fact we have
> to switch to kernel-mode on the guest and back again for every single GL
> call...
>
> If I can establish some kind of stable guest_virt->phys->host_virt
> mapping, many of the problems will just 'go away'. a way to interrupt
> qemu from user-mode on the guest without involving the guest kernel
> would be quite awesome also (theres really nothing we want the kernel to
> actually /do/ here, it just adds overhead).
>
I guess what you really want is some shm region between host and guess
that you can use as ring buffer. Then you could run a timer on the host
side to flush it or have some sort of callback when you urgently need to
flush it manually.
The benefit here is that you can actually make use of multiple threads.
There's no need to intercept the guest at all just because it wants to
issue some GL operations.
Alex
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] Address translation - virt->phys->ram
2010-02-22 18:56 ` Alexander Graf
@ 2010-02-23 15:46 ` Ian Molton
2010-02-23 15:54 ` Alexander Graf
0 siblings, 1 reply; 9+ messages in thread
From: Ian Molton @ 2010-02-23 15:46 UTC (permalink / raw)
To: Alexander Graf; +Cc: cam, qemu-devel
Alexander Graf wrote:
> I guess what you really want is some shm region between host and guess
> that you can use as ring buffer. Then you could run a timer on the host
> side to flush it or have some sort of callback when you urgently need to
> flush it manually.
>
> The benefit here is that you can actually make use of multiple threads.
> There's no need to intercept the guest at all just because it wants to
> issue some GL operations.
Something like that should work. The problem right now is mostly the
'some sort of callback'. Im not sure there exists any mechanism for the
guests userspace to interrupt qemu directly when running under kvm...
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] Address translation - virt->phys->ram
2010-02-23 15:46 ` Ian Molton
@ 2010-02-23 15:54 ` Alexander Graf
0 siblings, 0 replies; 9+ messages in thread
From: Alexander Graf @ 2010-02-23 15:54 UTC (permalink / raw)
To: Ian Molton; +Cc: cam, qemu-devel
On 23.02.2010, at 16:46, Ian Molton wrote:
> Alexander Graf wrote:
>
>> I guess what you really want is some shm region between host and guess
>> that you can use as ring buffer. Then you could run a timer on the host
>> side to flush it or have some sort of callback when you urgently need to
>> flush it manually.
>>
>> The benefit here is that you can actually make use of multiple threads.
>> There's no need to intercept the guest at all just because it wants to
>> issue some GL operations.
>
> Something like that should work. The problem right now is mostly the
> 'some sort of callback'. Im not sure there exists any mechanism for the
> guests userspace to interrupt qemu directly when running under kvm...
I'm not aware of any mechanism, but you could easily write a simple UIO driver that takes over this exact task.
Or you build on top of cam's shm patches and create a device node that exposes a poke ioctl.
Alex
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] Address translation - virt->phys->ram
2010-02-22 17:47 ` Ian Molton
2010-02-22 18:56 ` Alexander Graf
@ 2010-02-23 16:21 ` Anthony Liguori
1 sibling, 0 replies; 9+ messages in thread
From: Anthony Liguori @ 2010-02-23 16:21 UTC (permalink / raw)
To: Ian Molton; +Cc: qemu-devel
On 02/22/2010 11:47 AM, Ian Molton wrote:
> Anthony Liguori wrote:
>
>> On 02/22/2010 10:46 AM, Ian Molton wrote:
>>
>>> Anthony Liguori wrote:
>>>
>>>
>>>
>>>> cpu_physical_memory_map().
>>>>
>>>> But this function has some subtle characteristics. It may return a
>>>> bounce buffer if you attempt to map MMIO memory. There is a limited
>>>> pool of bounce buffers available so it may return NULL in the event that
>>>> it cannot allocate a bounce buffer.
>>>>
>>>> It may also return a partial result if you're attempting to map a region
>>>> that straddles multiple memory slots.
>>>>
>>>>
>>> Thanks. I had found this, but was unsure as to wether it was quite what
>>> I wanted. (also is it possible to tell when it has (eg.) allocated a
>>> bounce buffer?)
>>>
>>> Basically, I need to get buffer(s) from guest userspace into the hosts
>>> address space. The buffers are virtually contiguous but likely
>>> physically discontiguous. They are allocated with malloc() and theres
>>> nothing I can do about that.
>>>
>>> The obvious but slow solution would be to copy all the buffers into nice
>>> virtio-based scatter/gather buffers and feed them to the host that way,
>>> however its not fast enough.
>>>
>>>
>> Why is this slow?
>>
> Because the buffers will all have to be copied.
Why?
It sounds like your kernel driver is doing the wrong thing if you can't
preserve zero-copy from userspace.
> So far, switching from
> abusing an instruction to interrupt qemu to using virtio has incurred a
> roughly 5x slowdown.
If you post patches, we can help determine what you're doing that's
causing such a slow down.
Regards,
Anthony Liguori
> I'd guess much of this is down to the fact we have
> to switch to kernel-mode on the guest and back again for every single GL
> call...
>
> If I can establish some kind of stable guest_virt->phys->host_virt
> mapping, many of the problems will just 'go away'. a way to interrupt
> qemu from user-mode on the guest without involving the guest kernel
> would be quite awesome also (theres really nothing we want the kernel to
> actually /do/ here, it just adds overhead).
>
> -Ian
>
>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-02-23 16:21 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-22 13:59 [Qemu-devel] Address translation - virt->phys->ram Ian Molton
2010-02-22 14:35 ` Anthony Liguori
2010-02-22 16:46 ` Ian Molton
2010-02-22 16:52 ` Anthony Liguori
2010-02-22 17:47 ` Ian Molton
2010-02-22 18:56 ` Alexander Graf
2010-02-23 15:46 ` Ian Molton
2010-02-23 15:54 ` Alexander Graf
2010-02-23 16:21 ` Anthony Liguori
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).