-
Notifications
You must be signed in to change notification settings - Fork 1.4k
add uc_mem_read_virtual #2121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
add uc_mem_read_virtual #2121
Conversation
a977b1e
to
214c007
Compare
I have dreamed of this API for quite a while because It would be cool to even have translation API as suggested, but many QEMU MMU fill implementation has serious side effects. Why does "write_vritual" not work with snapshots? What's the current Lastly please target dev branch instead (for 2.2.0), the master branch is preparing for 2.1.3 and this change can't go into 2.1.3 obviously =). |
Sorry my bad.
It would work, it's just more code and maybe duplicated code, because of the snapshot handling. With a simple virtual to physical API it would be more simple.
In the current QEMU version is |
214c007
to
74ef179
Compare
CI is failing at this moment and I lack time to fix it. Will do later this week. |
There were also some bugs in my changes which causes the CI to fail.
I have added a testcase (on x86) and read the MMU implementations to verify this would work. As far as I see it works on every MMU expect for SPARC. Would it be OK to just document this issue? About the write: Would it be OK to just have a read implementation at the moment? |
Currently uc_mem_write does COW when memory snapshots are enabled. I would also expect this from a The problem is: This is quite complicated code and with the given |
I just revisited the Btw the typedef struct CPUClass {
// ...
bool (*tlb_fill)(CPUState *cpu, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
// ...
} |
7966d1b
to
6461b19
Compare
be29636
to
013877e
Compare
So I have added a I'll try to implement a |
The |
2900995
to
208eef5
Compare
@wtdcode write_virtual is also there and tested. |
Thanks for the brilliant work. I can review only a bit later as I'm having an urgent deadline on April 10. |
uc.c
Outdated
@@ -773,6 +773,136 @@ static bool check_mem_area(uc_engine *uc, uint64_t address, size_t size) | |||
return (count == size); | |||
} | |||
|
|||
uc_err uc_virtual_to_physical(uc_engine *uc, uint64_t address, uc_prot prot, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need prot here? Is there possible that different protections lead to different physical addresses? If the protection is only used for access check, is it trivial to skip such checks and only "translate" addresses for whatever protection? If that is not trivial, we can keep it as it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The prot is to have the mmu access rights checked. You might want to check if the corresponding address is write accessible. To check this you can call uc_virtual_to_physical(uc, addr, UC_PROT_WRITE, &paddr)
and check the return code.
Also it's necessary to have prot for a potential tlb_fill
call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But for “translation” itself, it has nothing to do with permissions, right? My point is that, from the semantics of the API, protection seems not necessary here though I understand tlb_fill requires this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For example, assume a memory region located at vaddr 0x2000 with paddr 0x1000 but with PROT_NONE, i.e. no one can access it. But from the perspective of emulator, the mapping is there exactly 0x2000 -> 0x1000 and we should be able to translate addresses no matter the protections.
However, I do understand that qemu code might not design for such cases. Therefore, if you think it is not feasible to translate addresses without protection, we can leave it as it is but with better docs.
Interrupted by some other things. Will continue my review a bit later. |
uc.c
Outdated
} | ||
|
||
UNICORN_EXPORT | ||
uc_err uc_mem_read_virtual(uc_engine *uc, uint64_t address, uc_prot prot, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just come up with alternative names: uc_vmem_read/write
. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, I'll adopt this.
* Only page aligned access is allowed, | ||
* because tlb_fill() might change the mappings | ||
*/ | ||
assert((addr & TARGET_PAGE_MASK) == ((addr + len - 1) & TARGET_PAGE_MASK)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this shall return UC_ERR_ARG
or more appropriate errors instead of assertions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use asserts for potential unicorn bugs and return errors for user bugs. This internal function is designed to only be called within one page. This is implemented in uc_mem_read_virtual
. Returning an error might cause a user to believe it's a bug in there code.
I'll write a comment about this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, but addr is from user inputs, no? uc_mem_read_virtual
seems using it directly? My concern is that this might cause the assertion too easy to trigger.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes addr is (more or less) from user input, but len is enforced to be maximum the rest of the page. What this assert checks is that the full len is on the same page. So the assert is in exactly what uc_mem_read_virtual
enforces. When we add other callers, they must handle this internal api the same way.
So I don't see how this assert triggers to early.
include/unicorn/unicorn.h
Outdated
for detailed error). | ||
*/ | ||
UNICORN_EXPORT | ||
uc_err uc_virtual_to_physical(uc_engine *uc, uint64_t address, uint32_t prot, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would suggest uc_vmem_translate
. What do you think?
|
||
@uc: handle returned by uc_open() | ||
@address: starting virtual memory address of bytes to get. | ||
@prot: The access type for the tlb lookup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As reviewed previously, if @prot
is essential, please document a bit more here. Like how different protections could affect the behavior. For example, what does uc_mem_read_virtual
with prot = UC_PROT_WRITE
imply?
208eef5
to
745eaf0
Compare
New api to read from, translate, or write to a virtual address. When using the MMU it's useful to direct use the virtual addresses.
745eaf0
to
1267722
Compare
@wtdcode is there anything missing for this getting merged? |
Hello Philipp, sorry for late because I'm on academic travel. I will give another review shortly. |
New api to read from a vaddr. When using the MMU it's useful to direct read from virtual addresses.
Needs some tests.
I'm not sure about a write_virtual() function. Could also be useful, but is a lot more complex to implement, because of snapshots.
A virtual to physical translate function would be also nice, but currently the
tlb_fill()
function has no probe argument.