diff options
author | nox <nox@FreeBSD.org> | 2008-05-13 03:09:52 +0800 |
---|---|---|
committer | nox <nox@FreeBSD.org> | 2008-05-13 03:09:52 +0800 |
commit | b1ed7571fea30264bfbd697c59ce90cc4c16cc94 (patch) | |
tree | d0d934f01dd878562fd8e4597d0939d23f41785b /emulators/kqemu-kmod | |
parent | a90201738324e4c2a2f85afab658dfb7876e3dc3 (diff) | |
download | freebsd-ports-gnome-b1ed7571fea30264bfbd697c59ce90cc4c16cc94.tar.gz freebsd-ports-gnome-b1ed7571fea30264bfbd697c59ce90cc4c16cc94.tar.zst freebsd-ports-gnome-b1ed7571fea30264bfbd697c59ce90cc4c16cc94.zip |
- Fix multiple qemu processes on amd64 SMP by actually using seperate
per-cpu gdts (the previous fix was only stable for one qemu process
at a time)
Relevant thread:
http://lists.freebsd.org/pipermail/freebsd-emulation/2008-May/004902.html
- Bump PORTREVISION
PR: ports/113430
Diffstat (limited to 'emulators/kqemu-kmod')
-rw-r--r-- | emulators/kqemu-kmod/Makefile | 2 | ||||
-rw-r--r-- | emulators/kqemu-kmod/files/patch-tssworkaround | 57 |
2 files changed, 50 insertions, 9 deletions
diff --git a/emulators/kqemu-kmod/Makefile b/emulators/kqemu-kmod/Makefile index 955ea30159b1..a07d18304e19 100644 --- a/emulators/kqemu-kmod/Makefile +++ b/emulators/kqemu-kmod/Makefile @@ -7,7 +7,7 @@ PORTNAME= kqemu PORTVERSION= 1.3.0.p11 -PORTREVISION= 5 +PORTREVISION= 6 CATEGORIES= emulators kld MASTER_SITES= http://fabrice.bellard.free.fr/qemu/ \ http://qemu.org/ \ diff --git a/emulators/kqemu-kmod/files/patch-tssworkaround b/emulators/kqemu-kmod/files/patch-tssworkaround index 00638fdd671f..bbd594488a8b 100644 --- a/emulators/kqemu-kmod/files/patch-tssworkaround +++ b/emulators/kqemu-kmod/files/patch-tssworkaround @@ -1,29 +1,70 @@ Index: kqemu-freebsd.c -@@ -38,6 +38,11 @@ +@@ -38,6 +38,14 @@ #else #include <machine/npx.h> #endif +#ifdef __x86_64__ ++#include <sys/smp.h> +#include <sys/pcpu.h> ++#include <machine/pcb.h> ++#include <machine/specialreg.h> +#include <machine/segments.h> +#include <machine/tss.h> +#endif #include "kqemu-kernel.h" -@@ -248,6 +253,19 @@ +@@ -248,6 +256,57 @@ va_end(ap); } +#ifdef __x86_64__ ++int kqemu_cpu0gdtfixed; ++int kqemu_gdts_used; ++struct user_segment_descriptor *kqemu_gdts; ++struct region_descriptor kqemu_r_newgdt; ++extern struct pcpu __pcpu[]; ++ +/* called with interrupts disabled */ -+void CDECL kqemu_tss_fixup(void) ++void CDECL kqemu_tss_fixup(unsigned long kerngdtbase) +{ + int gsel_tss = GSEL(GPROC0_SEL, SEL_KPL); ++ unsigned cpuid = PCPU_GET(cpuid); ++ struct user_segment_descriptor *newgdt = gdt; + -+ gdt_segs[GPROC0_SEL].ssd_base = (long) &common_tss[PCPU_GET(cpuid)]; ++ if (mp_ncpus <= 1 || kerngdtbase != (unsigned long)&gdt) ++ /* UP host or gdt already moved, nothing to do */ ++ return; ++ if (cpuid) { ++ /* move gdts of all but first cpu */ ++ if (!kqemu_gdts) ++ /* ++ * XXX gdt is allocated as ++ * struct user_segment_descriptor gdt[NGDT * MAXCPU]; ++ * so it has room for the moved copies; need to allocate at ++ * kldload (and only free if kqemu_gdts_used is zero) should this ++ * change in the future ++ */ ++ kqemu_gdts = &gdt[NGDT]; ++ ++kqemu_gdts_used; ++ newgdt = &kqemu_gdts[NGDT * (cpuid - 1)]; ++ bcopy(&gdt, newgdt, NGDT * sizeof(gdt[0])); ++ kqemu_r_newgdt.rd_limit = NGDT * sizeof(gdt[0]) - 1; ++ kqemu_r_newgdt.rd_base = (long) newgdt; ++ } else { ++ if (kqemu_cpu0gdtfixed) ++ return; ++ ++kqemu_cpu0gdtfixed; ++ } ++ gdt_segs[GPROC0_SEL].ssd_base = (long) &common_tss[cpuid]; + ssdtosyssd(&gdt_segs[GPROC0_SEL], -+ (struct system_segment_descriptor *)&gdt[GPROC0_SEL]); ++ (struct system_segment_descriptor *)&newgdt[GPROC0_SEL]); ++ if (cpuid) { ++ lgdt(&kqemu_r_newgdt); ++ wrmsr(MSR_GSBASE, (u_int64_t)&__pcpu[cpuid]); ++ wrmsr(MSR_KGSBASE, curthread->td_pcb->pcb_gsbase); ++ wrmsr(MSR_FSBASE, 0); ++ } + ltr(gsel_tss); +} +#endif @@ -49,7 +90,7 @@ Index: common/kernel.c +#ifdef __FreeBSD__ +#ifdef __x86_64__ + spin_lock(&g->lock); -+ kqemu_tss_fixup(); ++ kqemu_tss_fixup(s->kernel_gdt.base); + spin_unlock(&g->lock); +#endif +#endif @@ -57,13 +98,13 @@ Index: common/kernel.c if (s->mon_req == MON_REQ_IRQ) { struct kqemu_exception_regs *r; Index: kqemu-kernel.h -@@ -44,4 +44,10 @@ +@@ -48,4 +48,10 @@ void CDECL kqemu_log(const char *fmt, ...); +#ifdef __FreeBSD__ +#ifdef __x86_64__ -+void CDECL kqemu_tss_fixup(void); ++void CDECL kqemu_tss_fixup(unsigned long kerngdtbase); +#endif +#endif + |