Re: Re: [PATCH] linux-user/i386: Properly align signal frame
"The beginning of the structure, with pretaddr, should be just below 16-byte alignment." It is incorrect! The beginning of the structure, with pretaddr not aligned as 16-byte! On x86-64, It aligned as (16n - sizeof(void*)) because of instruction "call" ! > -原始邮件- > 发件人: "Richard Henderson" > 发送时间: 2023-05-24 13:50:43 (星期三) > 收件人: qemu-devel@nongnu.org > 抄送: fa...@mail.ustc.edu.cn, laur...@vivier.eu > 主题: Re: [PATCH] linux-user/i386: Properly align signal frame > > On 5/23/23 22:46, Richard Henderson wrote: > > The beginning of the structure, with pretaddr, should be just below > > 16-byte alignment. Disconnect fpstate from sigframe, just like the > > kernel does. > > > > Signed-off-by: Richard Henderson > > --- > > linux-user/i386/signal.c | 104 +-- > > tests/tcg/x86_64/sigstack.c | 33 ++ > > tests/tcg/x86_64/Makefile.target | 1 + > > 3 files changed, 90 insertions(+), 48 deletions(-) > > create mode 100644 tests/tcg/x86_64/sigstack.c > > Oops, meant to add > > Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1648 > > r~ > > > > > diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c > > index 60fa07d6f9..c49467de78 100644 > > --- a/linux-user/i386/signal.c > > +++ b/linux-user/i386/signal.c > > @@ -191,16 +191,7 @@ struct sigframe { > > struct target_fpstate fpstate_unused; > > abi_ulong extramask[TARGET_NSIG_WORDS-1]; > > char retcode[8]; > > - > > -/* > > - * This field will be 16-byte aligned in memory. Applying QEMU_ALIGNED > > - * to it ensures that the base of the frame has an appropriate > > alignment > > - * too. > > - */ > > -struct target_fpstate fpstate QEMU_ALIGNED(8); > > }; > > -#define TARGET_SIGFRAME_FXSAVE_OFFSET ( > > \ > > -offsetof(struct sigframe, fpstate) + TARGET_FPSTATE_FXSAVE_OFFSET) > > > > struct rt_sigframe { > > abi_ulong pretcode; > > @@ -210,27 +201,21 @@ struct rt_sigframe { > > struct target_siginfo info; > > struct target_ucontext uc; > > char retcode[8]; > > -struct target_fpstate fpstate QEMU_ALIGNED(8); > > }; > > -#define TARGET_RT_SIGFRAME_FXSAVE_OFFSET ( > > \ > > -offsetof(struct rt_sigframe, fpstate) + TARGET_FPSTATE_FXSAVE_OFFSET) > > #else > > - > > struct rt_sigframe { > > abi_ulong pretcode; > > struct target_ucontext uc; > > struct target_siginfo info; > > -struct target_fpstate fpstate QEMU_ALIGNED(16); > > }; > > -#define TARGET_RT_SIGFRAME_FXSAVE_OFFSET ( > > \ > > -offsetof(struct rt_sigframe, fpstate) + TARGET_FPSTATE_FXSAVE_OFFSET) > > #endif > > > > /* > >* Set up a signal frame. > >*/ > > > > -static void xsave_sigcontext(CPUX86State *env, struct > > target_fpstate_fxsave *fxsave, > > +static void xsave_sigcontext(CPUX86State *env, > > + struct target_fpstate_fxsave *fxsave, > >abi_ulong fxsave_addr) > > { > > if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { > > @@ -266,8 +251,9 @@ static void xsave_sigcontext(CPUX86State *env, struct > > target_fpstate_fxsave *fxs > > } > > > > static void setup_sigcontext(struct target_sigcontext *sc, > > -struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask, > > -abi_ulong fpstate_addr) > > + struct target_fpstate *fpstate, > > + CPUX86State *env, abi_ulong mask, > > + abi_ulong fpstate_addr) > > { > > CPUState *cs = env_cpu(env); > > #ifndef TARGET_X86_64 > > @@ -347,10 +333,11 @@ static void setup_sigcontext(struct target_sigcontext > > *sc, > >* Determine which stack to use.. > >*/ > > > > -static inline abi_ulong > > -get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t > > fxsave_offset) > > +static abi_ulong get_sigframe(struct target_sigaction *ka, CPUX86State > > *env, > > + size_t *frame_size, abi_ulong *fpsave_addr) > > { > > -unsigned long esp; > > +abi_ulong esp, orig; > > +size_t fpsave_size; > > > > /* Default to using normal stack */ > > esp = get_sp_from_cpustate(env); > > @@ -371,16 +358,23 @@ get_sigframe(struct target_sigaction *ka, CPUX86State > > *env, size_t fxsave_offset > > } > > #endif > > } > > +orig = esp; > > > > -if (!(env->features[FEAT_1_EDX] & CPUID_FXSR)) { > > -return (esp - (fxsave_offset + TARGET_FXSAVE_SIZE)) & -8ul; > > -} else if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { > > -return ((esp - TARGET_FXSAVE_SIZE) & -16ul) - fxsave_offset; > > +if (!(env->features[FEAT_1_ECX] & CPUID_EXT_XSAVE)) { > > +fpsave_size = TARGET_FXSAVE_SIZE; > > +esp = ROUND_DOWN(esp - fpsave_size,
[PATCH] linux-user: fix incorrect alignment of pretcode
sigframe::pretcode & rt_sigframe::pretcode must align of 16n-sizeof(void*) instead of 16n, Because rsp align of 16n before instruction "call" in caller, After "call", push address of "call" in caller. sp of begin in callee is 16n-sizeof(void*) Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1648 Signed-off-by: Fan WenJie --- linux-user/i386/signal.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/linux-user/i386/signal.c b/linux-user/i386/signal.c index 60fa07d6f9c..1f019689ae7 100644 --- a/linux-user/i386/signal.c +++ b/linux-user/i386/signal.c @@ -197,7 +197,8 @@ struct sigframe { * to it ensures that the base of the frame has an appropriate alignment * too. */ -struct target_fpstate fpstate QEMU_ALIGNED(8); +abi_ulong unused QEMU_ALIGNED(8); +struct target_fpstate fpstate; }; #define TARGET_SIGFRAME_FXSAVE_OFFSET (\ offsetof(struct sigframe, fpstate) + TARGET_FPSTATE_FXSAVE_OFFSET) @@ -210,7 +211,8 @@ struct rt_sigframe { struct target_siginfo info; struct target_ucontext uc; char retcode[8]; -struct target_fpstate fpstate QEMU_ALIGNED(8); +abi_ulong unused QEMU_ALIGNED(8); +struct target_fpstate fpstate; }; #define TARGET_RT_SIGFRAME_FXSAVE_OFFSET ( \ offsetof(struct rt_sigframe, fpstate) + TARGET_FPSTATE_FXSAVE_OFFSET) @@ -220,7 +222,8 @@ struct rt_sigframe { abi_ulong pretcode; struct target_ucontext uc; struct target_siginfo info; -struct target_fpstate fpstate QEMU_ALIGNED(16); +abi_ulong unused QEMU_ALIGNED(16); +struct target_fpstate fpstate; }; #define TARGET_RT_SIGFRAME_FXSAVE_OFFSET ( \ offsetof(struct rt_sigframe, fpstate) + TARGET_FPSTATE_FXSAVE_OFFSET) -- 2.40.1
Wine CE 8.5 Released, Cross Architecture Windows Emulator, Support Wow64, Base on wine and qemu
Wine CE is a compatibility layer capable of running Windows applications on Cross-architecture paltform of Linux, It base on wine and qemu, and support aarch64 and riscv64 Linux. It can emulate x86(32bit) x64, aarch64 windows app. Project Address: https://gitlab.com/wine-ce/wine-ce Binary Downnload: https://gitlab.com/wine-ce/wine-ce/-/releases/v8.5 Demo Video: RISCV 64: https://www.bilibili.com/video/BV1gv4y1578t AARCH 64: https://www.bilibili.com/video/BV1yc41157iS
[PATCH] linux-user: fix bug about incorrect base addresss of gdt on i386 and x86_64
On linux user mode, CPUX86State::gdt::base from Different CPUX86State Objects have same value, It is incorrect! Every CPUX86State::gdt::base Must points to independent memory space. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1405 Signed-off-by: fanwenjie --- linux-user/i386/cpu_loop.c | 9 + linux-user/main.c | 7 +++ 2 files changed, 16 insertions(+) diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c index 865413c..48511cd 100644 --- a/linux-user/i386/cpu_loop.c +++ b/linux-user/i386/cpu_loop.c @@ -314,8 +314,17 @@ void cpu_loop(CPUX86State *env) } } +static void target_cpu_free(void *obj) +{ +CPUArchState* env = ((CPUState*)obj)->env_ptr; +target_munmap(env->gdt.base, sizeof(uint64_t) * TARGET_GDT_ENTRIES); +g_free(obj); +} + void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) { +CPUState* cpu = env_cpu(env); +OBJECT(cpu)->free = target_cpu_free; env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; env->hflags |= HF_PE_MASK | HF_CPL_MASK; if (env->features[FEAT_1_EDX] & CPUID_SSE) { diff --git a/linux-user/main.c b/linux-user/main.c index a17fed0..3acd9b4 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -234,6 +234,13 @@ CPUArchState *cpu_copy(CPUArchState *env) new_cpu->tcg_cflags = cpu->tcg_cflags; memcpy(new_env, env, sizeof(CPUArchState)); +#if defined(TARGET_I386) || defined(TARGET_X86_64) +new_env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES, +PROT_READ|PROT_WRITE, +MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); +memcpy((void*)g2h_untagged(new_env->gdt.base), (void*)g2h_untagged(env->gdt.base), sizeof(uint64_t) * TARGET_GDT_ENTRIES); +OBJECT(new_cpu)->free = OBJECT(cpu)->free; +#endif /* Clone all break/watchpoints. Note: Once we support ptrace with hw-debug register access, make sure -- 2.34.1
Re: Re: Please review a important patch abort fix setting of CPUX86State::gdt::base
1. "The memcpy is definitely wrong, because you're casting a guest address into a host address, which is incorrect. You have to use g2h()." There is no need to use g2h(), Because there are both guest address whether source or dest memory. refer to "linux-user/i386/cpu_loop.c" target_cpu_copy_regs function, Only use g2h_untagged when convert gdt::base to gdt_table. I don't use and modify gdt_table, Only copy gdt::base from source CPU to dest CPU. They are same type so no needed to convert by g2h. 2. "I'm actually surprised that you need this for TARGET_X86_64 at all ..." GDT on QEMU User Mode is Pseudorandom GDT,It is NOT kernel private data structures. It is NOT Global Descriptor Table. It IS index table of fs and gs. And It is Thread local data. The Memory which gdt::base point can be modified by syscall SYS_set_thread_data. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/tls.c SYS_get_thread_area and SYS_set_thread_area used on x32 usually, But They can be syscalled on x64 when emulate Wow64 environment. - From: Richard Henderson Subject:Re: [PATCH] linux-user: fix bug about incorrect base addresss of gdt on i386 and x86_64 Date: Sat, 14 Jan 2023 19:32:59 -1000 User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.4.2 > On 1/3/23 01:38, fanwenjie wrote: On linux user mode, CPUX86State::gdt::base from Different CPUX86State Objects have same value, It is incorrect! Every CPUX86State::gdt::base Must points to independent memory space. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1405 Signed-off-by: fanwenjie --- linux-user/i386/cpu_loop.c | 9 + linux-user/main.c | 7 +++ 2 files changed, 16 insertions(+) diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c index 865413c..48511cd 100644 --- a/linux-user/i386/cpu_loop.c +++ b/linux-user/i386/cpu_loop.c @@ -314,8 +314,17 @@ void cpu_loop(CPUX86State *env) } } +static void target_cpu_free(void *obj) +{ +CPUArchState* env = ((CPUState*)obj)->env_ptr; +target_munmap(env->gdt.base, sizeof(uint64_t) * TARGET_GDT_ENTRIES); +g_free(obj); +} + void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) { +CPUState* cpu = env_cpu(env); +OBJECT(cpu)->free = target_cpu_free; env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; env->hflags |= HF_PE_MASK | HF_CPL_MASK; if (env->features[FEAT_1_EDX] & CPUID_SSE) { diff --git a/linux-user/main.c b/linux-user/main.c index a17fed0..3acd9b4 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -234,6 +234,13 @@ CPUArchState *cpu_copy(CPUArchState *env) new_cpu->tcg_cflags = cpu->tcg_cflags; memcpy(new_env, env, sizeof(CPUArchState)); +#if defined(TARGET_I386) || defined(TARGET_X86_64) +new_env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES, +PROT_READ|PROT_WRITE, +MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); +memcpy((void*)new_env->gdt.base, (void*)env->gdt.base, sizeof(uint64_t) * TARGET_GDT_ENTRIES); +OBJECT(new_cpu)->free = OBJECT(cpu)->free; +#endif This isn't a fantastic solution, because neither the ldt nor the gdt should be mapped into the user address space -- these are kernel private data structures. But cpu.h uses a target_ulong, and seg_helper.c is set up to load data from the guest, and it would be a medium sized job to address that. The memcpy is definitely wrong, because you're casting a guest address into a host address, which is incorrect. You have to use g2h(). I'm actually surprised that you need this for TARGET_X86_64 at all -- the two TLS segments don't really use the GDT at all, since fs_base and gs_base may be set directly.
Please review a important patch abort fix setting of CPUX86State::gdt::base
The patch fix bug abort settting CPUX86State::gdt::base on linux-user, the bug can write dirty data to emulated segment registers of x86 Patch address: https://lists.nongnu.org/archive/html/qemu-devel/2023-01/msg00142.html Bug description: https://gitlab.com/qemu-project/qemu/-/issues/1405 Because this bug has been fixed, Wine-CE Project can be succeeded, Wine-CE is a compatibility layer capable of running Windows applications on Cross-architecture paltform of Linux. It is base on Wine Project and Qemu Project. Project Address: https://gitlab.com/wine-ce/wine-ce
[PATCH] linux-user: fix bug about incorrect base addresss of idt and gdt on i386 and x86_64
On linux user mode, CPUX86State::idt::base and CPUX86State::gdt::base from Different CPUX86State Objects have same value, It is incorrect! Every CPUX86State::idt::base and Every CPUX86State::gdt::base Must points to independent memory space. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1405 Signed-off-by: fanwenjie --- linux-user/i386/cpu_loop.c | 10 ++ linux-user/main.c | 11 +++ 2 files changed, 21 insertions(+) diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c index 865413c08f..1f23bc5e3a 100644 --- a/linux-user/i386/cpu_loop.c +++ b/linux-user/i386/cpu_loop.c @@ -314,8 +314,18 @@ void cpu_loop(CPUX86State *env) } } +static void target_cpu_free(void *obj) +{ + CPUArchState* env = ((CPUState*)obj)->env_ptr; + target_munmap(env->idt.base, sizeof(uint64_t) * (env->idt.limit + 1)); + target_munmap(env->gdt.base, sizeof(uint64_t) * TARGET_GDT_ENTRIES); + g_free(obj); +} + void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) { + CPUState* cpu = env_cpu(env); + OBJECT(cpu)->free = target_cpu_free; env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; env->hflags |= HF_PE_MASK | HF_CPL_MASK; if (env->features[FEAT_1_EDX] & CPUID_SSE) { diff --git a/linux-user/main.c b/linux-user/main.c index a17fed045b..2276040548 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -234,6 +234,17 @@ CPUArchState *cpu_copy(CPUArchState *env) new_cpu->tcg_cflags = cpu->tcg_cflags; memcpy(new_env, env, sizeof(CPUArchState)); +#if defined(TARGET_I386) || defined(TARGET_X86_64) + new_env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES, + PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); + new_env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1), + PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); + memcpy((void*)new_env->gdt.base, (void*)env->gdt.base, sizeof(uint64_t) * TARGET_GDT_ENTRIES); + memcpy((void*)new_env->idt.base, (void*)env->idt.base, sizeof(uint64_t) * (env->idt.limit + 1)); + OBJECT(new_cpu)->free = OBJECT(cpu)->free; +#endif /* Clone all break/watchpoints. Note: Once we support ptrace with hw-debug register access, make sure -- 2.34.1
[PATCH] linux-user: fix bug about incorrect base addresss of idt and gdt on i386 and x86_64
From: fanwenjie On linux user mode, CPUX86State::idt::base and CPUX86State::gdt::base from Different CPUX86State Objects have same value, It is incorrect! Every CPUX86State::idt::base and Every CPUX86State::gdt::base Must points to independent memory space. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1405 Signed-off-by: fanwenjie --- linux-user/i386/cpu_loop.c | 10 ++ linux-user/main.c | 11 +++ 2 files changed, 21 insertions(+) diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c index 865413c08f..1f23bc5e3a 100644 --- a/linux-user/i386/cpu_loop.c +++ b/linux-user/i386/cpu_loop.c @@ -314,8 +314,18 @@ void cpu_loop(CPUX86State *env) } } +static void target_cpu_free(void *obj) +{ +CPUArchState* env = ((CPUState*)obj)->env_ptr; +target_munmap(env->idt.base, sizeof(uint64_t) * (env->idt.limit + 1)); +target_munmap(env->gdt.base, sizeof(uint64_t) * TARGET_GDT_ENTRIES); +g_free(obj); +} + void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) { +CPUState* cpu = env_cpu(env); +OBJECT(cpu)->free = target_cpu_free; env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; env->hflags |= HF_PE_MASK | HF_CPL_MASK; if (env->features[FEAT_1_EDX] & CPUID_SSE) { diff --git a/linux-user/main.c b/linux-user/main.c index a17fed045b..2276040548 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -234,6 +234,17 @@ CPUArchState *cpu_copy(CPUArchState *env) new_cpu->tcg_cflags = cpu->tcg_cflags; memcpy(new_env, env, sizeof(CPUArchState)); +#if defined(TARGET_I386) || defined(TARGET_X86_64) +new_env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES, +PROT_READ|PROT_WRITE, +MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); +new_env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1), +PROT_READ|PROT_WRITE, +MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); +memcpy((void*)new_env->gdt.base, (void*)env->gdt.base, sizeof(uint64_t) * TARGET_GDT_ENTRIES); +memcpy((void*)new_env->idt.base, (void*)env->idt.base, sizeof(uint64_t) * (env->idt.limit + 1)); +OBJECT(new_cpu)->free = OBJECT(cpu)->free; +#endif /* Clone all break/watchpoints. Note: Once we support ptrace with hw-debug register access, make sure -- 2.34.1
Recall: [PATCH] linux-user: fix bug about incorrect base addresss of idt and gdt on i386 and x86_64
The Patch has some problem, Please RECALL it! -原始邮件- 发件人:fa...@mail.ustc.edu.cn 发送时间:2023-01-01 23:57:06 (星期日) 收件人: qemu-devel@nongnu.org 抄送: qemu-devel@nongnu.org 主题: [PATCH] linux-user: fix bug about incorrect base addresss of idt and gdt on i386 and x86_64 From 4601a624f40b2c89e7df2dec1adffb4f4308ba2d Mon Sep 17 00:00:00 2001 From: fanwenjie Date: Sun, 1 Jan 2023 23:13:34 +0800 Subject: [PATCH] linux-user: fix bug about incorrect base addresss of idt and gdt on i386 and x86_64 Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1405 Signed-off-by: fanwenjie --- linux-user/main.c | 13 + 1 file changed, 13 insertions(+) diff --git a/linux-user/main.c b/linux-user/main.c index a17fed045b..5d673c95b3 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -171,6 +171,12 @@ void fork_end(int child) __thread CPUState *thread_cpu; +#if defined(TARGET_I386) || defined(TARGET_X86_64) +#include +__thread alignas(TARGET_PAGE_SIZE) static uint64_t gdt_base[TARGET_GDT_ENTRIES]; +__thread alignas(TARGET_PAGE_SIZE) static uint64_t idt_base[TARGET_PAGE_SIZE / sizeof(uint64_t)]; +#endif + bool qemu_cpu_is_self(CPUState *cpu) { return thread_cpu == cpu; @@ -235,6 +241,13 @@ CPUArchState *cpu_copy(CPUArchState *env) new_cpu->tcg_cflags = cpu->tcg_cflags; memcpy(new_env, env, sizeof(CPUArchState)); +#if defined(TARGET_I386) || defined(TARGET_X86_64) +memcpy(idt_base, (void*)new_env->idt.base, sizeof(uint64_t) * (new_env->idt.limit + 1)); +memcpy(gdt_base, (void*)new_env->gdt.base, sizeof(uint64_t) * TARGET_GDT_ENTRIES); +new_env->idt.base = (target_ulong)idt_base; +new_env->gdt.base = (target_ulong)gdt_base; +#endif + /* Clone all break/watchpoints. Note: Once we support ptrace with hw-debug register access, make sure BP_CPU break/watchpoints are handled correctly on clone. */ -- 2.34.1
[PATCH] linux-user: fix bug about incorrect base addresss of idt and gdt on i386 and x86_64
From 4601a624f40b2c89e7df2dec1adffb4f4308ba2d Mon Sep 17 00:00:00 2001 From: fanwenjie Date: Sun, 1 Jan 2023 23:13:34 +0800 Subject: [PATCH] linux-user: fix bug about incorrect base addresss of idt and gdt on i386 and x86_64 Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1405 Signed-off-by: fanwenjie --- linux-user/main.c | 13 + 1 file changed, 13 insertions(+) diff --git a/linux-user/main.c b/linux-user/main.c index a17fed045b..5d673c95b3 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -171,6 +171,12 @@ void fork_end(int child) __thread CPUState *thread_cpu; +#if defined(TARGET_I386) || defined(TARGET_X86_64) +#include +__thread alignas(TARGET_PAGE_SIZE) static uint64_t gdt_base[TARGET_GDT_ENTRIES]; +__thread alignas(TARGET_PAGE_SIZE) static uint64_t idt_base[TARGET_PAGE_SIZE / sizeof(uint64_t)]; +#endif + bool qemu_cpu_is_self(CPUState *cpu) { return thread_cpu == cpu; @@ -235,6 +241,13 @@ CPUArchState *cpu_copy(CPUArchState *env) new_cpu->tcg_cflags = cpu->tcg_cflags; memcpy(new_env, env, sizeof(CPUArchState)); +#if defined(TARGET_I386) || defined(TARGET_X86_64) +memcpy(idt_base, (void*)new_env->idt.base, sizeof(uint64_t) * (new_env->idt.limit + 1)); +memcpy(gdt_base, (void*)new_env->gdt.base, sizeof(uint64_t) * TARGET_GDT_ENTRIES); +new_env->idt.base = (target_ulong)idt_base; +new_env->gdt.base = (target_ulong)gdt_base; +#endif + /* Clone all break/watchpoints. Note: Once we support ptrace with hw-debug register access, make sure BP_CPU break/watchpoints are handled correctly on clone. */ -- 2.34.1
[PATCH] linux-user: fix bug about missing signum convert of sigqueue
From 4ebe8a67ed7c4b1220957b2b67a62ba60e0e80ec Mon Sep 17 00:00:00 2001 From: fanwenjie Date: Wed, 31 Aug 2022 11:55:25 +0800 Subject: [PATCH] linux-user: fix bug about missing signum convert of sigqueue Signed-off-by: fanwenjie --- linux-user/syscall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f409121202..3e5ab4f0b2 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -9690,7 +9690,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, } target_to_host_siginfo(, p); unlock_user(p, arg3, 0); -ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, )); +ret = get_errno(sys_rt_sigqueueinfo(arg1, target_to_host_signal(arg2), )); } return ret; case TARGET_NR_rt_tgsigqueueinfo: @@ -9703,7 +9703,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, } target_to_host_siginfo(, p); unlock_user(p, arg4, 0); -ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, )); +ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, target_to_host_signal(arg3), )); } return ret; #ifdef TARGET_NR_sigreturn --