diff options
Diffstat (limited to 'linux-user')
-rw-r--r-- | linux-user/aarch64/signal.c | 4 | ||||
-rw-r--r-- | linux-user/arm/cpu_loop.c | 2 | ||||
-rw-r--r-- | linux-user/elfload.c | 168 | ||||
-rw-r--r-- | linux-user/fd-trans.h | 10 | ||||
-rw-r--r-- | linux-user/flatload.c | 1 | ||||
-rw-r--r-- | linux-user/gen-vdso.c | 43 | ||||
-rw-r--r-- | linux-user/hppa/cpu_loop.c | 12 | ||||
-rw-r--r-- | linux-user/loongarch64/cpu_loop.c | 25 | ||||
-rw-r--r-- | linux-user/main.c | 13 | ||||
-rw-r--r-- | linux-user/mips/target_signal.h | 1 | ||||
-rw-r--r-- | linux-user/mmap.c | 3 | ||||
-rw-r--r-- | linux-user/qemu.h | 5 | ||||
-rw-r--r-- | linux-user/signal.c | 4 | ||||
-rw-r--r-- | linux-user/syscall.c | 38 | ||||
-rw-r--r-- | linux-user/syscall_defs.h | 4 | ||||
-rw-r--r-- | linux-user/user-internals.h | 1 | ||||
-rw-r--r-- | linux-user/xtensa/signal.c | 1 |
17 files changed, 257 insertions, 78 deletions
diff --git a/linux-user/aarch64/signal.c b/linux-user/aarch64/signal.c index bc7a138..d50cab7 100644 --- a/linux-user/aarch64/signal.c +++ b/linux-user/aarch64/signal.c @@ -248,7 +248,7 @@ static void target_setup_za_record(struct target_za_context *za, for (i = 0; i < vl; ++i) { uint64_t *z = (void *)za + TARGET_ZA_SIG_ZAV_OFFSET(vq, i); for (j = 0; j < vq * 2; ++j) { - __put_user_e(env->zarray[i].d[j], z + j, le); + __put_user_e(env->za_state.za[i].d[j], z + j, le); } } } @@ -397,7 +397,7 @@ static bool target_restore_za_record(CPUARMState *env, for (i = 0; i < vl; ++i) { uint64_t *z = (void *)za + TARGET_ZA_SIG_ZAV_OFFSET(vq, i); for (j = 0; j < vq * 2; ++j) { - __get_user_e(env->zarray[i].d[j], z + j, le); + __get_user_e(env->za_state.za[i].d[j], z + j, le); } } return true; diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c index 7416e32..33f6395 100644 --- a/linux-user/arm/cpu_loop.c +++ b/linux-user/arm/cpu_loop.c @@ -25,6 +25,7 @@ #include "signal-common.h" #include "semihosting/common-semi.h" #include "exec/page-protection.h" +#include "exec/mmap-lock.h" #include "user/page-protection.h" #include "target/arm/syndrome.h" @@ -362,6 +363,7 @@ void cpu_loop(CPUARMState *env) switch (n) { case ARM_NR_cacheflush: /* nop */ + env->regs[0] = 0; break; case ARM_NR_set_tls: cpu_set_tls(env, env->regs[0]); diff --git a/linux-user/elfload.c b/linux-user/elfload.c index fa83d78..ea21410 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -10,7 +10,9 @@ #include "user/tswap-target.h" #include "user/page-protection.h" #include "exec/page-protection.h" +#include "exec/mmap-lock.h" #include "exec/translation-block.h" +#include "exec/tswap.h" #include "user/guest-base.h" #include "user-internals.h" #include "signal-common.h" @@ -749,7 +751,23 @@ enum { ARM_HWCAP_A64_SSBS = 1 << 28, ARM_HWCAP_A64_SB = 1 << 29, ARM_HWCAP_A64_PACA = 1 << 30, - ARM_HWCAP_A64_PACG = 1UL << 31, + ARM_HWCAP_A64_PACG = 1ULL << 31, + ARM_HWCAP_A64_GCS = 1ULL << 32, + ARM_HWCAP_A64_CMPBR = 1ULL << 33, + ARM_HWCAP_A64_FPRCVT = 1ULL << 34, + ARM_HWCAP_A64_F8MM8 = 1ULL << 35, + ARM_HWCAP_A64_F8MM4 = 1ULL << 36, + ARM_HWCAP_A64_SVE_F16MM = 1ULL << 37, + ARM_HWCAP_A64_SVE_ELTPERM = 1ULL << 38, + ARM_HWCAP_A64_SVE_AES2 = 1ULL << 39, + ARM_HWCAP_A64_SVE_BFSCALE = 1ULL << 40, + ARM_HWCAP_A64_SVE2P2 = 1ULL << 41, + ARM_HWCAP_A64_SME2P2 = 1ULL << 42, + ARM_HWCAP_A64_SME_SBITPERM = 1ULL << 43, + ARM_HWCAP_A64_SME_AES = 1ULL << 44, + ARM_HWCAP_A64_SME_SFEXPA = 1ULL << 45, + ARM_HWCAP_A64_SME_STMOP = 1ULL << 46, + ARM_HWCAP_A64_SME_SMOP4 = 1ULL << 47, ARM_HWCAP2_A64_DCPODP = 1 << 0, ARM_HWCAP2_A64_SVE2 = 1 << 1, @@ -796,6 +814,25 @@ enum { ARM_HWCAP2_A64_SME_F16F16 = 1ULL << 42, ARM_HWCAP2_A64_MOPS = 1ULL << 43, ARM_HWCAP2_A64_HBC = 1ULL << 44, + ARM_HWCAP2_A64_SVE_B16B16 = 1ULL << 45, + ARM_HWCAP2_A64_LRCPC3 = 1ULL << 46, + ARM_HWCAP2_A64_LSE128 = 1ULL << 47, + ARM_HWCAP2_A64_FPMR = 1ULL << 48, + ARM_HWCAP2_A64_LUT = 1ULL << 49, + ARM_HWCAP2_A64_FAMINMAX = 1ULL << 50, + ARM_HWCAP2_A64_F8CVT = 1ULL << 51, + ARM_HWCAP2_A64_F8FMA = 1ULL << 52, + ARM_HWCAP2_A64_F8DP4 = 1ULL << 53, + ARM_HWCAP2_A64_F8DP2 = 1ULL << 54, + ARM_HWCAP2_A64_F8E4M3 = 1ULL << 55, + ARM_HWCAP2_A64_F8E5M2 = 1ULL << 56, + ARM_HWCAP2_A64_SME_LUTV2 = 1ULL << 57, + ARM_HWCAP2_A64_SME_F8F16 = 1ULL << 58, + ARM_HWCAP2_A64_SME_F8F32 = 1ULL << 59, + ARM_HWCAP2_A64_SME_SF8FMA = 1ULL << 60, + ARM_HWCAP2_A64_SME_SF8DP4 = 1ULL << 61, + ARM_HWCAP2_A64_SME_SF8DP2 = 1ULL << 62, + ARM_HWCAP2_A64_POE = 1ULL << 63, }; #define ELF_HWCAP get_elf_hwcap() @@ -878,13 +915,21 @@ uint64_t get_elf_hwcap2(void) GET_FEATURE_ID(aa64_sme_fa64, ARM_HWCAP2_A64_SME_FA64); GET_FEATURE_ID(aa64_hbc, ARM_HWCAP2_A64_HBC); GET_FEATURE_ID(aa64_mops, ARM_HWCAP2_A64_MOPS); + GET_FEATURE_ID(aa64_sve2p1, ARM_HWCAP2_A64_SVE2P1); + GET_FEATURE_ID(aa64_sme2, (ARM_HWCAP2_A64_SME2 | + ARM_HWCAP2_A64_SME_I16I32 | + ARM_HWCAP2_A64_SME_BI32I32)); + GET_FEATURE_ID(aa64_sme2p1, ARM_HWCAP2_A64_SME2P1); + GET_FEATURE_ID(aa64_sme_b16b16, ARM_HWCAP2_A64_SME_B16B16); + GET_FEATURE_ID(aa64_sme_f16f16, ARM_HWCAP2_A64_SME_F16F16); + GET_FEATURE_ID(aa64_sve_b16b16, ARM_HWCAP2_A64_SVE_B16B16); return hwcaps; } const char *elf_hwcap_str(uint32_t bit) { - static const char *hwcap_str[] = { + static const char * const hwcap_str[] = { [__builtin_ctz(ARM_HWCAP_A64_FP )] = "fp", [__builtin_ctz(ARM_HWCAP_A64_ASIMD )] = "asimd", [__builtin_ctz(ARM_HWCAP_A64_EVTSTRM )] = "evtstrm", @@ -917,6 +962,22 @@ const char *elf_hwcap_str(uint32_t bit) [__builtin_ctz(ARM_HWCAP_A64_SB )] = "sb", [__builtin_ctz(ARM_HWCAP_A64_PACA )] = "paca", [__builtin_ctz(ARM_HWCAP_A64_PACG )] = "pacg", + [__builtin_ctzll(ARM_HWCAP_A64_GCS )] = "gcs", + [__builtin_ctzll(ARM_HWCAP_A64_CMPBR )] = "cmpbr", + [__builtin_ctzll(ARM_HWCAP_A64_FPRCVT)] = "fprcvt", + [__builtin_ctzll(ARM_HWCAP_A64_F8MM8 )] = "f8mm8", + [__builtin_ctzll(ARM_HWCAP_A64_F8MM4 )] = "f8mm4", + [__builtin_ctzll(ARM_HWCAP_A64_SVE_F16MM)] = "svef16mm", + [__builtin_ctzll(ARM_HWCAP_A64_SVE_ELTPERM)] = "sveeltperm", + [__builtin_ctzll(ARM_HWCAP_A64_SVE_AES2)] = "sveaes2", + [__builtin_ctzll(ARM_HWCAP_A64_SVE_BFSCALE)] = "svebfscale", + [__builtin_ctzll(ARM_HWCAP_A64_SVE2P2)] = "sve2p2", + [__builtin_ctzll(ARM_HWCAP_A64_SME2P2)] = "sme2p2", + [__builtin_ctzll(ARM_HWCAP_A64_SME_SBITPERM)] = "smesbitperm", + [__builtin_ctzll(ARM_HWCAP_A64_SME_AES)] = "smeaes", + [__builtin_ctzll(ARM_HWCAP_A64_SME_SFEXPA)] = "smesfexpa", + [__builtin_ctzll(ARM_HWCAP_A64_SME_STMOP)] = "smestmop", + [__builtin_ctzll(ARM_HWCAP_A64_SME_SMOP4)] = "smesmop4", }; return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; @@ -924,7 +985,7 @@ const char *elf_hwcap_str(uint32_t bit) const char *elf_hwcap2_str(uint32_t bit) { - static const char *hwcap_str[] = { + static const char * const hwcap_str[] = { [__builtin_ctz(ARM_HWCAP2_A64_DCPODP )] = "dcpodp", [__builtin_ctz(ARM_HWCAP2_A64_SVE2 )] = "sve2", [__builtin_ctz(ARM_HWCAP2_A64_SVEAES )] = "sveaes", @@ -970,6 +1031,24 @@ const char *elf_hwcap2_str(uint32_t bit) [__builtin_ctzll(ARM_HWCAP2_A64_SME_F16F16 )] = "smef16f16", [__builtin_ctzll(ARM_HWCAP2_A64_MOPS )] = "mops", [__builtin_ctzll(ARM_HWCAP2_A64_HBC )] = "hbc", + [__builtin_ctzll(ARM_HWCAP2_A64_SVE_B16B16 )] = "sveb16b16", + [__builtin_ctzll(ARM_HWCAP2_A64_LRCPC3 )] = "lrcpc3", + [__builtin_ctzll(ARM_HWCAP2_A64_LSE128 )] = "lse128", + [__builtin_ctzll(ARM_HWCAP2_A64_FPMR )] = "fpmr", + [__builtin_ctzll(ARM_HWCAP2_A64_LUT )] = "lut", + [__builtin_ctzll(ARM_HWCAP2_A64_FAMINMAX )] = "faminmax", + [__builtin_ctzll(ARM_HWCAP2_A64_F8CVT )] = "f8cvt", + [__builtin_ctzll(ARM_HWCAP2_A64_F8FMA )] = "f8fma", + [__builtin_ctzll(ARM_HWCAP2_A64_F8DP4 )] = "f8dp4", + [__builtin_ctzll(ARM_HWCAP2_A64_F8DP2 )] = "f8dp2", + [__builtin_ctzll(ARM_HWCAP2_A64_F8E4M3 )] = "f8e4m3", + [__builtin_ctzll(ARM_HWCAP2_A64_F8E5M2 )] = "f8e5m2", + [__builtin_ctzll(ARM_HWCAP2_A64_SME_LUTV2 )] = "smelutv2", + [__builtin_ctzll(ARM_HWCAP2_A64_SME_F8F16 )] = "smef8f16", + [__builtin_ctzll(ARM_HWCAP2_A64_SME_F8F32 )] = "smef8f32", + [__builtin_ctzll(ARM_HWCAP2_A64_SME_SF8DP4 )] = "smesf8dp4", + [__builtin_ctzll(ARM_HWCAP2_A64_SME_SF8DP2 )] = "smesf8dp2", + [__builtin_ctzll(ARM_HWCAP2_A64_POE )] = "poe", }; return bit < ARRAY_SIZE(hwcap_str) ? hwcap_str[bit] : NULL; @@ -2121,9 +2200,12 @@ static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) memcpy(to, from, n); } -#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN static void bswap_ehdr(struct elfhdr *ehdr) { + if (!target_needs_bswap()) { + return; + } + bswap16s(&ehdr->e_type); /* Object file type */ bswap16s(&ehdr->e_machine); /* Architecture */ bswap32s(&ehdr->e_version); /* Object file version */ @@ -2141,8 +2223,11 @@ static void bswap_ehdr(struct elfhdr *ehdr) static void bswap_phdr(struct elf_phdr *phdr, int phnum) { - int i; - for (i = 0; i < phnum; ++i, ++phdr) { + if (!target_needs_bswap()) { + return; + } + + for (int i = 0; i < phnum; ++i, ++phdr) { bswap32s(&phdr->p_type); /* Segment type */ bswap32s(&phdr->p_flags); /* Segment flags */ bswaptls(&phdr->p_offset); /* Segment file offset */ @@ -2156,8 +2241,11 @@ static void bswap_phdr(struct elf_phdr *phdr, int phnum) static void bswap_shdr(struct elf_shdr *shdr, int shnum) { - int i; - for (i = 0; i < shnum; ++i, ++shdr) { + if (!target_needs_bswap()) { + return; + } + + for (int i = 0; i < shnum; ++i, ++shdr) { bswap32s(&shdr->sh_name); bswap32s(&shdr->sh_type); bswaptls(&shdr->sh_flags); @@ -2173,6 +2261,10 @@ static void bswap_shdr(struct elf_shdr *shdr, int shnum) static void bswap_sym(struct elf_sym *sym) { + if (!target_needs_bswap()) { + return; + } + bswap32s(&sym->st_name); bswaptls(&sym->st_value); bswaptls(&sym->st_size); @@ -2182,6 +2274,10 @@ static void bswap_sym(struct elf_sym *sym) #ifdef TARGET_MIPS static void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) { + if (!target_needs_bswap()) { + return; + } + bswap16s(&abiflags->version); bswap32s(&abiflags->ases); bswap32s(&abiflags->isa_ext); @@ -2189,15 +2285,6 @@ static void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) bswap32s(&abiflags->flags2); } #endif -#else -static inline void bswap_ehdr(struct elfhdr *ehdr) { } -static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { } -static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { } -static inline void bswap_sym(struct elf_sym *sym) { } -#ifdef TARGET_MIPS -static inline void bswap_mips_abiflags(Mips_elf_abiflags_v0 *abiflags) { } -#endif -#endif #ifdef USE_ELF_CORE_DUMP static int elf_core_dump(int, const CPUArchState *); @@ -3143,11 +3230,11 @@ static bool parse_elf_properties(const ImageSource *src, * The contents of a valid PT_GNU_PROPERTY is a sequence of uint32_t. * Swap most of them now, beyond the header and namesz. */ -#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN - for (int i = 4; i < n / 4; i++) { - bswap32s(note.data + i); + if (target_needs_bswap()) { + for (int i = 4; i < n / 4; i++) { + bswap32s(note.data + i); + } } -#endif /* * Note that nhdr is 3 words, and that the "name" described by namesz @@ -3999,9 +4086,12 @@ struct target_elf_prpsinfo { char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ }; -#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN static void bswap_prstatus(struct target_elf_prstatus *prstatus) { + if (!target_needs_bswap()) { + return; + } + prstatus->pr_info.si_signo = tswap32(prstatus->pr_info.si_signo); prstatus->pr_info.si_code = tswap32(prstatus->pr_info.si_code); prstatus->pr_info.si_errno = tswap32(prstatus->pr_info.si_errno); @@ -4019,6 +4109,10 @@ static void bswap_prstatus(struct target_elf_prstatus *prstatus) static void bswap_psinfo(struct target_elf_prpsinfo *psinfo) { + if (!target_needs_bswap()) { + return; + } + psinfo->pr_flag = tswapal(psinfo->pr_flag); psinfo->pr_uid = tswap16(psinfo->pr_uid); psinfo->pr_gid = tswap16(psinfo->pr_gid); @@ -4030,21 +4124,19 @@ static void bswap_psinfo(struct target_elf_prpsinfo *psinfo) static void bswap_note(struct elf_note *en) { + if (!target_needs_bswap()) { + return; + } + bswap32s(&en->n_namesz); bswap32s(&en->n_descsz); bswap32s(&en->n_type); } -#else -static inline void bswap_prstatus(struct target_elf_prstatus *p) { } -static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {} -static inline void bswap_note(struct elf_note *en) { } -#endif /* HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN */ /* * Calculate file (dump) size of given memory region. */ -static size_t vma_dump_size(target_ulong start, target_ulong end, - unsigned long flags) +static size_t vma_dump_size(vaddr start, vaddr end, int flags) { /* The area must be readable. */ if (!(flags & PAGE_READ)) { @@ -4237,14 +4329,14 @@ static int dump_write(int fd, const void *ptr, size_t size) return (0); } -static int wmr_page_unprotect_regions(void *opaque, target_ulong start, - target_ulong end, unsigned long flags) +static int wmr_page_unprotect_regions(void *opaque, vaddr start, + vaddr end, int flags) { if ((flags & (PAGE_WRITE | PAGE_WRITE_ORG)) == PAGE_WRITE_ORG) { size_t step = MAX(TARGET_PAGE_SIZE, qemu_real_host_page_size()); while (1) { - page_unprotect(start, 0); + page_unprotect(NULL, start, 0); if (end - start <= step) { break; } @@ -4259,8 +4351,8 @@ typedef struct { size_t size; } CountAndSizeRegions; -static int wmr_count_and_size_regions(void *opaque, target_ulong start, - target_ulong end, unsigned long flags) +static int wmr_count_and_size_regions(void *opaque, vaddr start, + vaddr end, int flags) { CountAndSizeRegions *css = opaque; @@ -4274,8 +4366,8 @@ typedef struct { off_t offset; } FillRegionPhdr; -static int wmr_fill_region_phdr(void *opaque, target_ulong start, - target_ulong end, unsigned long flags) +static int wmr_fill_region_phdr(void *opaque, vaddr start, + vaddr end, int flags) { FillRegionPhdr *d = opaque; struct elf_phdr *phdr = d->phdr; @@ -4297,8 +4389,8 @@ static int wmr_fill_region_phdr(void *opaque, target_ulong start, return 0; } -static int wmr_write_region(void *opaque, target_ulong start, - target_ulong end, unsigned long flags) +static int wmr_write_region(void *opaque, vaddr start, + vaddr end, int flags) { int fd = *(int *)opaque; size_t size = vma_dump_size(start, end, flags); diff --git a/linux-user/fd-trans.h b/linux-user/fd-trans.h index 910faaf..e14f960 100644 --- a/linux-user/fd-trans.h +++ b/linux-user/fd-trans.h @@ -36,6 +36,16 @@ static inline void fd_trans_init(void) qemu_mutex_init(&target_fd_trans_lock); } +static inline void fd_trans_prefork(void) +{ + qemu_mutex_lock(&target_fd_trans_lock); +} + +static inline void fd_trans_postfork(void) +{ + qemu_mutex_unlock(&target_fd_trans_lock); +} + static inline TargetFdDataFunc fd_trans_target_to_host_data(int fd) { if (fd < 0) { diff --git a/linux-user/flatload.c b/linux-user/flatload.c index d5cb183..4beb3ed 100644 --- a/linux-user/flatload.c +++ b/linux-user/flatload.c @@ -35,6 +35,7 @@ #include "qemu.h" #include "exec/page-protection.h" +#include "exec/mmap-lock.h" #include "user-internals.h" #include "loader.h" #include "user-mmap.h" diff --git a/linux-user/gen-vdso.c b/linux-user/gen-vdso.c index 721f38d..aeaa927 100644 --- a/linux-user/gen-vdso.c +++ b/linux-user/gen-vdso.c @@ -56,13 +56,14 @@ static unsigned rt_sigreturn_addr; int main(int argc, char **argv) { - FILE *inf, *outf; + FILE *inf = NULL, *outf = NULL; long total_len; const char *prefix = "vdso"; const char *inf_name; const char *outf_name = NULL; - unsigned char *buf; + unsigned char *buf = NULL; bool need_bswap; + int ret = EXIT_FAILURE; while (1) { int opt = getopt(argc, argv, "o:p:r:s:"); @@ -112,9 +113,21 @@ int main(int argc, char **argv) * We expect the vdso to be small, on the order of one page, * therefore we do not expect a partial read. */ - fseek(inf, 0, SEEK_END); + if (fseek(inf, 0, SEEK_END) < 0) { + goto perror_inf; + } total_len = ftell(inf); - fseek(inf, 0, SEEK_SET); + if (total_len < 0) { + goto perror_inf; + } + if (fseek(inf, 0, SEEK_SET) < 0) { + goto perror_inf; + } + + if (total_len < EI_NIDENT) { + fprintf(stderr, "%s: file too small (truncated?)\n", inf_name); + return EXIT_FAILURE; + } buf = malloc(total_len); if (buf == NULL) { @@ -129,7 +142,6 @@ int main(int argc, char **argv) fprintf(stderr, "%s: incomplete read\n", inf_name); return EXIT_FAILURE; } - fclose(inf); /* * Identify which elf flavor we're processing. @@ -205,19 +217,24 @@ int main(int argc, char **argv) fprintf(outf, " .rt_sigreturn_ofs = 0x%x,\n", rt_sigreturn_addr); fprintf(outf, "};\n"); - /* - * Everything should have gone well. - */ - if (fclose(outf)) { - goto perror_outf; + ret = EXIT_SUCCESS; + + cleanup: + free(buf); + + if (outf && fclose(outf) != 0) { + ret = EXIT_FAILURE; + } + if (inf && fclose(inf) != 0) { + ret = EXIT_FAILURE; } - return EXIT_SUCCESS; + return ret; perror_inf: perror(inf_name); - return EXIT_FAILURE; + goto cleanup; perror_outf: perror(outf_name); - return EXIT_FAILURE; + goto cleanup; } diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c index 890e758..9abaad5 100644 --- a/linux-user/hppa/cpu_loop.c +++ b/linux-user/hppa/cpu_loop.c @@ -112,7 +112,7 @@ static abi_ulong hppa_lws(CPUHPPAState *env) void cpu_loop(CPUHPPAState *env) { CPUState *cs = env_cpu(env); - abi_ulong ret; + abi_ulong ret, si_code = 0; int trapnr; while (1) { @@ -169,7 +169,15 @@ void cpu_loop(CPUHPPAState *env) force_sig_fault(TARGET_SIGFPE, TARGET_FPE_CONDTRAP, env->iaoq_f); break; case EXCP_ASSIST: - force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f); + #define set_si_code(mask, val) \ + if (env->fr[0] & mask) { si_code = val; } + set_si_code(R_FPSR_FLG_I_MASK, TARGET_FPE_FLTRES); + set_si_code(R_FPSR_FLG_U_MASK, TARGET_FPE_FLTUND); + set_si_code(R_FPSR_FLG_O_MASK, TARGET_FPE_FLTOVF); + set_si_code(R_FPSR_FLG_Z_MASK, TARGET_FPE_FLTDIV); + set_si_code(R_FPSR_FLG_V_MASK, TARGET_FPE_FLTINV); + #undef set_si_code + force_sig_fault(TARGET_SIGFPE, si_code, env->iaoq_f); break; case EXCP_BREAK: force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f); diff --git a/linux-user/loongarch64/cpu_loop.c b/linux-user/loongarch64/cpu_loop.c index 0614d3d..ec8a06c 100644 --- a/linux-user/loongarch64/cpu_loop.c +++ b/linux-user/loongarch64/cpu_loop.c @@ -11,6 +11,12 @@ #include "user/cpu_loop.h" #include "signal-common.h" +/* Break codes */ +enum { + BRK_OVERFLOW = 6, + BRK_DIVZERO = 7 +}; + void cpu_loop(CPULoongArchState *env) { CPUState *cs = env_cpu(env); @@ -66,9 +72,26 @@ void cpu_loop(CPULoongArchState *env) force_sig_fault(TARGET_SIGFPE, si_code, env->pc); break; case EXCP_DEBUG: - case EXCCODE_BRK: force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); break; + case EXCCODE_BRK: + { + unsigned int opcode; + + get_user_u32(opcode, env->pc); + + switch (opcode & 0x7fff) { + case BRK_OVERFLOW: + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTOVF, env->pc); + break; + case BRK_DIVZERO: + force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->pc); + break; + default: + force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); + } + } + break; case EXCCODE_BCE: force_sig_fault(TARGET_SIGSYS, TARGET_SI_KERNEL, env->pc); break; diff --git a/linux-user/main.c b/linux-user/main.c index e2ec597..f4f2007 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -40,7 +40,6 @@ #include "qemu/plugin.h" #include "user/guest-base.h" #include "user/page-protection.h" -#include "exec/exec-all.h" #include "exec/gdbstub.h" #include "gdbstub/user.h" #include "tcg/startup.h" @@ -123,6 +122,7 @@ static const char *last_log_filename; #endif unsigned long reserved_va; +unsigned long guest_addr_max; static void usage(int exitcode); @@ -149,12 +149,14 @@ void fork_start(void) cpu_list_lock(); qemu_plugin_user_prefork_lock(); gdbserver_fork_start(); + fd_trans_prefork(); } void fork_end(pid_t pid) { bool child = pid == 0; + fd_trans_postfork(); qemu_plugin_user_postfork(child); mmap_fork_end(child); if (child) { @@ -820,7 +822,7 @@ int main(int argc, char **argv, char **envp) opt_one_insn_per_tb, &error_abort); object_property_set_int(OBJECT(accel), "tb-size", opt_tb_size, &error_abort); - ac->init_machine(NULL); + ac->init_machine(accel, NULL); } /* @@ -859,6 +861,13 @@ int main(int argc, char **argv, char **envp) /* MAX_RESERVED_VA + 1 is a large power of 2, so is aligned. */ reserved_va = max_reserved_va; } + if (reserved_va != 0) { + guest_addr_max = reserved_va; + } else if (MIN(TARGET_VIRT_ADDR_SPACE_BITS, TARGET_ABI_BITS) <= 32) { + guest_addr_max = UINT32_MAX; + } else { + guest_addr_max = ~0ul; + } /* * Temporarily disable diff --git a/linux-user/mips/target_signal.h b/linux-user/mips/target_signal.h index fa542c1..4481426 100644 --- a/linux-user/mips/target_signal.h +++ b/linux-user/mips/target_signal.h @@ -64,7 +64,6 @@ typedef struct target_sigaltstack { #define TARGET_SA_NODEFER 0x40000000 #define TARGET_SA_RESTART 0x10000000 #define TARGET_SA_RESETHAND 0x80000000 -#define TARGET_SA_RESTORER 0x04000000 /* Only for O32 */ #define TARGET_MINSIGSTKSZ 2048 diff --git a/linux-user/mmap.c b/linux-user/mmap.c index d1f36e6..002e1e6 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -21,6 +21,7 @@ #include "trace.h" #include "exec/log.h" #include "exec/page-protection.h" +#include "exec/mmap-lock.h" #include "exec/tb-flush.h" #include "exec/translation-block.h" #include "qemu.h" @@ -644,7 +645,7 @@ static abi_long mmap_h_eq_g(abi_ulong start, abi_ulong len, * * However, this case is rather common with executable images, * so the workaround is important for even trivial tests, whereas - * the mmap of of a file being extended is less common. + * the mmap of a file being extended is less common. */ static abi_long mmap_h_lt_g(abi_ulong start, abi_ulong len, int host_prot, int mmap_flags, int page_flags, int fd, diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 5f00750..0b19fa4 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -2,7 +2,7 @@ #define QEMU_H #include "cpu.h" -#include "exec/cpu_ldst.h" +#include "accel/tcg/cpu-ldst.h" #include "user/abitypes.h" #include "user/page-protection.h" @@ -362,4 +362,7 @@ void *lock_user_string(abi_ulong guest_addr); #define unlock_user_struct(host_ptr, guest_addr, copy) \ unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0) +/* Clone cpu state */ +CPUArchState *cpu_copy(CPUArchState *env); + #endif /* QEMU_H */ diff --git a/linux-user/signal.c b/linux-user/signal.c index 4dafc2c..cd0e739 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -750,7 +750,7 @@ void force_sigsegv(int oldsig) } #endif -void cpu_loop_exit_sigsegv(CPUState *cpu, target_ulong addr, +void cpu_loop_exit_sigsegv(CPUState *cpu, vaddr addr, MMUAccessType access_type, bool maperr, uintptr_t ra) { const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; @@ -766,7 +766,7 @@ void cpu_loop_exit_sigsegv(CPUState *cpu, target_ulong addr, cpu_loop_exit_restore(cpu, ra); } -void cpu_loop_exit_sigbus(CPUState *cpu, target_ulong addr, +void cpu_loop_exit_sigbus(CPUState *cpu, vaddr addr, MMUAccessType access_type, uintptr_t ra) { const TCGCPUOps *tcg_ops = cpu->cc->tcg_ops; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 8bfe491..91360a0 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -26,6 +26,7 @@ #include "tcg/startup.h" #include "target_mman.h" #include "exec/page-protection.h" +#include "exec/mmap-lock.h" #include "exec/tb-flush.h" #include "exec/translation-block.h" #include <elf.h> @@ -789,6 +790,10 @@ safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff, int, outfd, loff_t *, poutoff, size_t, length, unsigned int, flags) #endif +#if defined(TARGET_NR_fchmodat2) && defined(__NR_fchmodat2) +safe_syscall4(int, fchmodat2, int, dfd, const char *, filename, + unsigned short, mode, unsigned int, flags) +#endif /* We do ioctl like this rather than via safe_syscall3 to preserve the * "third argument might be integer or pointer or not present" behaviour of @@ -6742,10 +6747,9 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, int pid_child = ret; pid_fd = pidfd_open(pid_child, 0); if (pid_fd >= 0) { - fcntl(pid_fd, F_SETFD, fcntl(pid_fd, F_GETFL) - | FD_CLOEXEC); + qemu_set_cloexec(pid_fd); } else { - pid_fd = 0; + pid_fd = 0; } #endif put_user_u32(pid_fd, parent_tidptr); @@ -8134,8 +8138,8 @@ static void open_self_maps_4(const struct open_self_maps_data *d, * Callback for walk_memory_regions, when read_self_maps() fails. * Proceed without the benefit of host /proc/self/maps cross-check. */ -static int open_self_maps_3(void *opaque, target_ulong guest_start, - target_ulong guest_end, unsigned long flags) +static int open_self_maps_3(void *opaque, vaddr guest_start, + vaddr guest_end, int flags) { static const MapInfo mi = { .is_priv = true }; @@ -8146,8 +8150,8 @@ static int open_self_maps_3(void *opaque, target_ulong guest_start, /* * Callback for walk_memory_regions, when read_self_maps() succeeds. */ -static int open_self_maps_2(void *opaque, target_ulong guest_start, - target_ulong guest_end, unsigned long flags) +static int open_self_maps_2(void *opaque, vaddr guest_start, + vaddr guest_end, int flags) { const struct open_self_maps_data *d = opaque; uintptr_t host_start = (uintptr_t)g2h_untagged(guest_start); @@ -8234,6 +8238,9 @@ static int open_self_stat(CPUArchState *cpu_env, int fd) } else if (i == 3) { /* ppid */ g_string_printf(buf, FMT_pid " ", getppid()); + } else if (i == 4) { + /* pgid */ + g_string_printf(buf, FMT_pid " ", getpgrp()); } else if (i == 19) { /* num_threads */ int cpus = 0; @@ -10710,6 +10717,15 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, unlock_user(p, arg2, 0); return ret; #endif +#if defined(TARGET_NR_fchmodat2) && defined(__NR_fchmodat2) + case TARGET_NR_fchmodat2: + if (!(p = lock_user_string(arg2))) { + return -TARGET_EFAULT; + } + ret = get_errno(safe_fchmodat2(arg1, p, arg3, arg4)); + unlock_user(p, arg2, 0); + return ret; +#endif case TARGET_NR_getpriority: /* Note that negative values are valid for getpriority, so we must differentiate based on errno settings. */ @@ -11626,10 +11642,14 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, case TARGET_NR_nanosleep: { struct timespec req, rem; - target_to_host_timespec(&req, arg1); + if (target_to_host_timespec(&req, arg1)) { + return -TARGET_EFAULT; + } ret = get_errno(safe_nanosleep(&req, &rem)); if (is_error(ret) && arg2) { - host_to_target_timespec(arg2, &rem); + if (host_to_target_timespec(arg2, &rem)) { + return -TARGET_EFAULT; + } } } return ret; diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 5d22759..df26a2d 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -515,10 +515,6 @@ struct target_sigaction { abi_ulong _sa_handler; #endif target_sigset_t sa_mask; -#ifdef TARGET_ARCH_HAS_SA_RESTORER - /* ??? This is always present, but ignored unless O32. */ - abi_ulong sa_restorer; -#endif }; #else struct target_old_sigaction { diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h index 4aa253b..691b9a1 100644 --- a/linux-user/user-internals.h +++ b/linux-user/user-internals.h @@ -19,7 +19,6 @@ #define LINUX_USER_USER_INTERNALS_H #include "user/thunk.h" -#include "exec/exec-all.h" #include "qemu/log.h" extern char *exec_path; diff --git a/linux-user/xtensa/signal.c b/linux-user/xtensa/signal.c index 6514b8d..ef8b0c3 100644 --- a/linux-user/xtensa/signal.c +++ b/linux-user/xtensa/signal.c @@ -241,7 +241,6 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, give_sigsegv: force_sigsegv(sig); - return; } static void restore_sigcontext(CPUXtensaState *env, |