mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-04 16:23:55 -06:00
-----BEGIN PGP SIGNATURE-----
iQIcBAABAgAGBQJaZ0sNAAoJEPMMOL0/L7480bQP/i5QO0c4MrXJ7VaEa1u6ubfv AELpodvD6hm0qDT8OIH/4g1PRFZvB1OGg1wd8sZg/aLLbxfiKQ0kR+6Kq+W6LLJY qD4xddVZnBVlcSDwGn6Rg3bStgISOBr+Z7fAOtLOFc6BJz5JryU4PSPLXIb4gxtX 0DXPXnSSTj+yZUjoG408aqAAlFRgbbXcY9Yhx3hblEO3ZJWAv7qrtoL67PEgB4kh j2t/6SSpEvsrmsb1g4N0/NMb6csOAwcA3kiTiOE2fGhc6vS7hUpcQPDQi/FHfkWD Q9Qe5y1TUE+JCc1VAdjWy3+42yH+IFpJo8lshJZw0tSGk3GCXeRUI6jlsawMphq/ Xo9zrIcXcTY/1ZWB9FWypr0orFLMphQPY6cwEu/60QvzQA8coeJk27zqXgL/G78y 7bNqLhMVz1JkKO4uCkRGQVJuijLo3aO3OeFSEnl8QoZInoOaPd+aVh/FCs57hV3r mcXT+ab9lbNrx0BTMI8Cr4HzvHH5cAfNg8hK/hh9rVHkAopLGvHkNJWOLbtAawds MulpKlLMnuntU/LGfAVU+ccttWt8Hfd5vRwS3Ex99sTIU/yBYh8iSAHh0lweE00p RmGMuVn+aXwcnDAsTXR6+8Zn5GzK+o9eifwlFdhI7AkCPwhra4fVodi0d/0imvGE XHLy02hVBGUp+Hoyf0/r =2ycl -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-2.12-pull-request' into staging # gpg: Signature made Tue 23 Jan 2018 14:47:41 GMT # gpg: using RSA key 0xF30C38BD3F2FBE3C # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" # gpg: aka "Laurent Vivier <laurent@vivier.eu>" # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier2/tags/linux-user-for-2.12-pull-request: linux-user: implement renameat2 page_unprotect(): handle calls to pages that are PAGE_WRITE linux-user: Propagate siginfo_t through to handle_cpu_signal() linux-user: remove nmi.c and fw-path-provider.c linux-user: Add getcpu() support linux-user: Add AT_SECURE auxval linux-user: Fix sched_get/setaffinity conversion linux-user/mmap.c: Avoid choosing NULL as start address linux-user: Translate flags argument to dup3 syscall linux-user: Don't use CMSG_ALIGN(sizeof struct cmsghdr) linux-user: Fix length calculations in host_to_target_cmsg() linux-user: wrap fork() in a start/end exclusive section linux-user: Fix locking order in fork_start() Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
0f79bfe38a
10 changed files with 328 additions and 149 deletions
|
@ -2181,29 +2181,41 @@ int page_unprotect(target_ulong address, uintptr_t pc)
|
|||
|
||||
/* if the page was really writable, then we change its
|
||||
protection back to writable */
|
||||
if ((p->flags & PAGE_WRITE_ORG) && !(p->flags & PAGE_WRITE)) {
|
||||
host_start = address & qemu_host_page_mask;
|
||||
host_end = host_start + qemu_host_page_size;
|
||||
|
||||
prot = 0;
|
||||
if (p->flags & PAGE_WRITE_ORG) {
|
||||
current_tb_invalidated = false;
|
||||
for (addr = host_start ; addr < host_end ; addr += TARGET_PAGE_SIZE) {
|
||||
p = page_find(addr >> TARGET_PAGE_BITS);
|
||||
p->flags |= PAGE_WRITE;
|
||||
prot |= p->flags;
|
||||
|
||||
/* and since the content will be modified, we must invalidate
|
||||
the corresponding translated code. */
|
||||
current_tb_invalidated |= tb_invalidate_phys_page(addr, pc);
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
if (DEBUG_TB_CHECK_GATE) {
|
||||
tb_invalidate_check(addr);
|
||||
if (p->flags & PAGE_WRITE) {
|
||||
/* If the page is actually marked WRITE then assume this is because
|
||||
* this thread raced with another one which got here first and
|
||||
* set the page to PAGE_WRITE and did the TB invalidate for us.
|
||||
*/
|
||||
#ifdef TARGET_HAS_PRECISE_SMC
|
||||
TranslationBlock *current_tb = tb_find_pc(pc);
|
||||
if (current_tb) {
|
||||
current_tb_invalidated = tb_cflags(current_tb) & CF_INVALID;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
mprotect((void *)g2h(host_start), qemu_host_page_size,
|
||||
prot & PAGE_BITS);
|
||||
} else {
|
||||
host_start = address & qemu_host_page_mask;
|
||||
host_end = host_start + qemu_host_page_size;
|
||||
|
||||
prot = 0;
|
||||
for (addr = host_start; addr < host_end; addr += TARGET_PAGE_SIZE) {
|
||||
p = page_find(addr >> TARGET_PAGE_BITS);
|
||||
p->flags |= PAGE_WRITE;
|
||||
prot |= p->flags;
|
||||
|
||||
/* and since the content will be modified, we must invalidate
|
||||
the corresponding translated code. */
|
||||
current_tb_invalidated |= tb_invalidate_phys_page(addr, pc);
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
if (DEBUG_TB_CHECK_GATE) {
|
||||
tb_invalidate_check(addr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
mprotect((void *)g2h(host_start), qemu_host_page_size,
|
||||
prot & PAGE_BITS);
|
||||
}
|
||||
mmap_unlock();
|
||||
/* If current TB was invalidated return to main loop */
|
||||
return current_tb_invalidated ? 2 : 1;
|
||||
|
|
|
@ -57,12 +57,13 @@ static void cpu_exit_tb_from_sighandler(CPUState *cpu, sigset_t *old_set)
|
|||
the effective address of the memory exception. 'is_write' is 1 if a
|
||||
write caused the exception and otherwise 0'. 'old_set' is the
|
||||
signal set which should be restored */
|
||||
static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
|
||||
static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
|
||||
int is_write, sigset_t *old_set)
|
||||
{
|
||||
CPUState *cpu = current_cpu;
|
||||
CPUClass *cc;
|
||||
int ret;
|
||||
unsigned long address = (unsigned long)info->si_addr;
|
||||
|
||||
/* We must handle PC addresses from two different sources:
|
||||
* a call return address and a signal frame address.
|
||||
|
@ -103,7 +104,18 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address,
|
|||
pc, address, is_write, *(unsigned long *)old_set);
|
||||
#endif
|
||||
/* XXX: locking issue */
|
||||
if (is_write && h2g_valid(address)) {
|
||||
/* Note that it is important that we don't call page_unprotect() unless
|
||||
* this is really a "write to nonwriteable page" fault, because
|
||||
* page_unprotect() assumes that if it is called for an access to
|
||||
* a page that's writeable this means we had two threads racing and
|
||||
* another thread got there first and already made the page writeable;
|
||||
* so we will retry the access. If we were to call page_unprotect()
|
||||
* for some other kind of fault that should really be passed to the
|
||||
* guest, we'd end up in an infinite loop of retrying the faulting
|
||||
* access.
|
||||
*/
|
||||
if (is_write && info->si_signo == SIGSEGV && info->si_code == SEGV_ACCERR &&
|
||||
h2g_valid(address)) {
|
||||
switch (page_unprotect(h2g(address), pc)) {
|
||||
case 0:
|
||||
/* Fault not caused by a page marked unwritable to protect
|
||||
|
@ -215,9 +227,8 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
|||
#endif
|
||||
pc = EIP_sig(uc);
|
||||
trapno = TRAP_sig(uc);
|
||||
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
|
||||
trapno == 0xe ?
|
||||
(ERROR_sig(uc) >> 1) & 1 : 0,
|
||||
return handle_cpu_signal(pc, info,
|
||||
trapno == 0xe ? (ERROR_sig(uc) >> 1) & 1 : 0,
|
||||
&MASK_sig(uc));
|
||||
}
|
||||
|
||||
|
@ -261,9 +272,8 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
|||
#endif
|
||||
|
||||
pc = PC_sig(uc);
|
||||
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
|
||||
TRAP_sig(uc) == 0xe ?
|
||||
(ERROR_sig(uc) >> 1) & 1 : 0,
|
||||
return handle_cpu_signal(pc, info,
|
||||
TRAP_sig(uc) == 0xe ? (ERROR_sig(uc) >> 1) & 1 : 0,
|
||||
&MASK_sig(uc));
|
||||
}
|
||||
|
||||
|
@ -341,8 +351,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
|||
is_write = 1;
|
||||
}
|
||||
#endif
|
||||
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
|
||||
is_write, &uc->uc_sigmask);
|
||||
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
|
||||
}
|
||||
|
||||
#elif defined(__alpha__)
|
||||
|
@ -372,8 +381,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
|||
is_write = 1;
|
||||
}
|
||||
|
||||
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
|
||||
is_write, &uc->uc_sigmask);
|
||||
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
|
||||
}
|
||||
#elif defined(__sparc__)
|
||||
|
||||
|
@ -432,8 +440,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
|||
break;
|
||||
}
|
||||
}
|
||||
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
|
||||
is_write, sigmask);
|
||||
return handle_cpu_signal(pc, info, is_write, sigmask);
|
||||
}
|
||||
|
||||
#elif defined(__arm__)
|
||||
|
@ -466,9 +473,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
|||
* later processor; on v5 we will always report this as a read).
|
||||
*/
|
||||
is_write = extract32(uc->uc_mcontext.error_code, 11, 1);
|
||||
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
|
||||
is_write,
|
||||
&uc->uc_sigmask);
|
||||
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
@ -495,8 +500,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
|
|||
/* Ignore bits 23 & 24, controlling indexing. */
|
||||
|| (insn & 0x3a400000) == 0x28000000); /* C3.3.7,14-16 */
|
||||
|
||||
return handle_cpu_signal(pc, (uintptr_t)info->si_addr,
|
||||
is_write, &uc->uc_sigmask);
|
||||
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
|
||||
}
|
||||
|
||||
#elif defined(__ia64)
|
||||
|
@ -529,9 +533,7 @@ int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
return handle_cpu_signal(ip, (unsigned long)info->si_addr,
|
||||
is_write,
|
||||
(sigset_t *)&uc->uc_sigmask);
|
||||
return handle_cpu_signal(ip, info, is_write, (sigset_t *)&uc->uc_sigmask);
|
||||
}
|
||||
|
||||
#elif defined(__s390__)
|
||||
|
@ -583,8 +585,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
|||
}
|
||||
break;
|
||||
}
|
||||
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
|
||||
is_write, &uc->uc_sigmask);
|
||||
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
|
||||
}
|
||||
|
||||
#elif defined(__mips__)
|
||||
|
@ -599,8 +600,7 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
|||
|
||||
/* XXX: compute is_write */
|
||||
is_write = 0;
|
||||
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
|
||||
is_write, &uc->uc_sigmask);
|
||||
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue