aboutsummaryrefslogtreecommitdiff
path: root/emulators/kqemu-kmod-devel
diff options
context:
space:
mode:
authorJuergen Lock <nox@FreeBSD.org>2009-05-30 19:50:09 +0000
committerJuergen Lock <nox@FreeBSD.org>2009-05-30 19:50:09 +0000
commit0cbfdbee46004362a104238baa166134d7f6b06a (patch)
tree9b9920e47b3b5a5258023adf8b42b2eb52348e57 /emulators/kqemu-kmod-devel
parent675686ab8b49a8a8f5ad591a998b3143dab453af (diff)
downloadports-0cbfdbee46004362a104238baa166134d7f6b06a.tar.gz
ports-0cbfdbee46004362a104238baa166134d7f6b06a.zip
- Allow specifying nonstandard base/kernel source dirs by defining
SRC_BASE or SYSDIR respectively. - Add a few extra patches: [1] - An old patch by Enache Adrian to help NetBSD/OpenBSD guest support: http://lists.gnu.org/archive/html/qemu-devel/2007-11/msg00125.html (At least NetBSD still has issues seeing pci devices with acpi and assigning correct pci irqs without acpi when there still is an mptable which the qemu/kvm bios now defaults to providing, and it also doesn't seem to like most of the emulated nic choices - but these remaining issues have nothing to do with kqemu. I'll post a little more on the qemu-devel list...) - A patch series by Jan Kiszka from May 2009: http://lists.gnu.org/archive/html/qemu-devel/2009-05/msg01550.html In the unlikely case that any of these patches cause regressions please define WITHOUT_EXTRA_PATCHES and post details about your host _and_ guest on freebsd-emulation@freebsd.org . Obtained from: qemu-devel mailinglist [1]
Notes
Notes: svn path=/head/; revision=234863
Diffstat (limited to 'emulators/kqemu-kmod-devel')
-rw-r--r--emulators/kqemu-kmod-devel/Makefile16
-rw-r--r--emulators/kqemu-kmod-devel/files/extra-patch-ea-200711-netbsd70
-rw-r--r--emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-0151
-rw-r--r--emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-02102
-rw-r--r--emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-0338
-rw-r--r--emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-04108
-rw-r--r--emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-05155
7 files changed, 538 insertions, 2 deletions
diff --git a/emulators/kqemu-kmod-devel/Makefile b/emulators/kqemu-kmod-devel/Makefile
index 96af32721578..8f9873a3dcdb 100644
--- a/emulators/kqemu-kmod-devel/Makefile
+++ b/emulators/kqemu-kmod-devel/Makefile
@@ -7,7 +7,7 @@
PORTNAME= kqemu
PORTVERSION= 1.4.0.p1
-PORTREVISION= 2
+PORTREVISION= 3
CATEGORIES= emulators kld
MASTER_SITES= http://bellard.org/qemu/ \
http://qemu.org/ \
@@ -48,7 +48,10 @@ KMODDIR= /boot/modules
MAKE_ENV+= KMODDIR="${KMODDIR}"
-.if !exists(${SRC_BASE}/sys/Makefile)
+SYSDIR?= ${SRC_BASE}/sys
+MAKE_ENV+= SYSDIR="${SYSDIR}"
+
+.if !exists(${SYSDIR}/Makefile)
IGNORE= requires kernel source to be installed
.endif
@@ -74,6 +77,15 @@ post-patch:
.if ${OSVERSION} >= 701100 && (${OSVERSION} < 800000 || ${OSVERSION} >= 800046)
@cd ${WRKSRC} && ${PATCH} -R --quiet < ${FILESDIR}/patch-tssworkaround
.endif
+# Apply extra patches from the qemu-devel list; in the unlikely case that
+# these cause regressions please define WITHOUT_EXTRA_PATCHES and post
+# details about your host _and_ guest on freebsd-emulation@freebsd.org
+# - Thanx!
+.if !defined(WITHOUT_EXTRA_PATCHES)
+ for i in ${FILESDIR}/extra-patch-*; do \
+ ${PATCH} -d ${WRKSRC} --quiet <$$i;\
+ done
+.endif
do-build:
@(cd ${BUILD_WRKSRC}/common; ${SETENV} ${MAKE_ENV} ${GMAKE} ${MAKE_FLAGS} Makefile ${MAKE_ARGS} ${ALL_TARGET})
diff --git a/emulators/kqemu-kmod-devel/files/extra-patch-ea-200711-netbsd b/emulators/kqemu-kmod-devel/files/extra-patch-ea-200711-netbsd
new file mode 100644
index 000000000000..ea1c410c44d2
--- /dev/null
+++ b/emulators/kqemu-kmod-devel/files/extra-patch-ea-200711-netbsd
@@ -0,0 +1,70 @@
+From: 3n4ch3@gmail.com (Enache Adrian)
+Subject: [Qemu-devel] [kqemu patch] get Open/NetBSD to work with the kqemu
+ accelerator
+Date: Mon, 5 Nov 2007 22:00:12 +0200
+Message-ID: <281a8e2bec2c45bce8b89bf96457995c.fa6dd951@aerenchyma>
+To: qemu-devel@nongnu.org
+
+[sorry if this is the wrong list, but I haven't figured out any public
+ address where I could send kqemu bug reports and patches]
+
+Currently, both NetBSD and OpenBSD are hanging or crashing when running
+on qemu with the kqemu accelerator enabled.
+
+This happens because both systems are using a weird scheme where they
+are loading the GDT table with LGDT up-front (with the limit set to
+the maximum), but are growing the table and actually mapping the memory
+behind it only when needed.
+(see src/sys/arch/i386/i386/gdt.c in both source trees)
+
+That is causing the kqemu accelerator to generate a page fault in
+update_dt_cache() when trying to fill its 'soft' tlb with pages that
+are beyond the real end of the GDT table.
+
+With this diff applied, NetBSD and OpenBSD seem to run fine with
+kqemu + user-only virtualization (I've tried netbsd-4.0-rc2 and
+openbsd 4.2).
+
+Full virtualization (-kernel-kqemu) doesn't work yet for different
+reasons (I think).
+
+Regards,
+Adi
+
+Index: common/monitor.c
+--- xx/kqemu-1.3.0pre11/common/monitor.c Tue Feb 6 23:02:00 2007
++++ kqemu-1.3.0pre11/common/monitor.c Mon Nov 5 18:59:58 2007
+@@ -990,7 +990,8 @@ static void *map_vaddr(struct kqemu_state *s, unsigned
+ e = &s->soft_tlb[(addr >> PAGE_SHIFT) & (SOFT_TLB_SIZE - 1)];
+ redo:
+ if (e->vaddr[(is_user << 1) + is_write] != (addr & PAGE_MASK)) {
+- soft_tlb_fill(s, addr, is_write, is_user);
++ if(cpu_x86_handle_mmu_fault(s, addr, is_write, is_user, 1))
++ return NULL;
+ goto redo;
+ } else {
+ taddr = e->addend + addr;
+@@ -1802,6 +1803,11 @@ static void update_dt_cache(struct kqemu_state *s, int
+ page_end = dt_end;
+ sel2 = sel + (page_end - dt_ptr);
+ ptr = map_vaddr(s, dt_ptr, 0, 0);
++ if(!ptr)
++ /* Open/NetBSD have a 'dynamic' GDT, but they load the gdt
++ register with LGDT only once and with a limit far beyond
++ the end of the memory actually mapped for the table */
++ goto skip_the_rest;
+ ram_addr = ram_ptr_to_ram_addr(s, ptr);
+ if (dt_changed ||
+ s->dt_ram_addr[dt_type][pindex] != ram_addr ||
+@@ -1818,7 +1824,7 @@ static void update_dt_cache(struct kqemu_state *s, int
+ sel_end = (s->dt_limit[dt_type] + 1) & ~7;
+ if (sel < sel_end)
+ reset_dt_entries(s, dt_type, sel, sel_end);
+-
++skip_the_rest:
+ s->dt_base[dt_type] = base;
+ s->dt_limit[dt_type] = limit;
+ }
+
+
+
diff --git a/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-01 b/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-01
new file mode 100644
index 000000000000..7102987fde6d
--- /dev/null
+++ b/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-01
@@ -0,0 +1,51 @@
+From: jan.kiszka@siemens.com (Jan Kiszka)
+Subject: [Qemu-devel] [PATCH 1/5] kqemu: x86-64: Run 16-bit-stack-return in
+ ring 0
+Date: Fri, 29 May 2009 19:18:31 +0200
+Message-ID: <20090529171831.14265.89986.stgit@mchn012c.ww002.siemens.net>
+To: qemu-devel@nongnu.org
+
+The fix-up code for returning to 16 bit stack segments is currently
+executed in ring 1. This has the side effect that the interrupt flag
+remains cleared on return from ring 1 to the guest's ring 3 as its
+IOPL is 0 (ie. iret can only modify IF when run in ring 0).
+
+Fix this by moving the 32 bit return trampoline into ring 0.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+
+ common/kernel.c | 8 ++++----
+ 1 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/common/kernel.c b/common/kernel.c
+index 6a88452..1d7a69e 100644
+Index: common/kernel.c
+--- a/common/kernel.c
++++ b/common/kernel.c
+@@ -422,8 +422,8 @@ struct kqemu_state *kqemu_init(struct kqemu_init *d,
+ #ifdef __x86_64__
+ s->monitor_ds_sel = 0; /* no need for a specific data segment */
+ /* used for 16 bit esp fix */
+- s->monitor_cs32_sel = (s->monitor_selector_base + (7 << 3)) | 1;
+- s->monitor_ss16_sel = (s->monitor_selector_base + (6 << 3)) | 1;
++ s->monitor_cs32_sel = s->monitor_selector_base + (7 << 3);
++ s->monitor_ss16_sel = s->monitor_selector_base + (6 << 3);
+ s->monitor_ss_null_sel = (s->monitor_selector_base + (1 << 3)) | 3;
+ #else
+ s->monitor_ds_sel = s->monitor_selector_base + (1 << 3);
+@@ -495,9 +495,9 @@ struct kqemu_state *kqemu_init(struct kqemu_init *d,
+ 0, 0xfffff, 0xa09a); /* long mode segment */
+ set_seg((uint32_t *)(dt_table + (s->monitor_ss16_sel >> 3)),
+ (s->monitor_data_vaddr + offsetof(struct kqemu_state, stack)) & ~0xffff,
+- 0xffff, 0x00b2); /* SS16 segment for 16 bit ESP fix */
++ 0xffff, 0x0092); /* SS16 segment for 16 bit ESP fix */
+ set_seg((uint32_t *)(dt_table + (s->monitor_cs32_sel >> 3)),
+- 0, 0xfffff, 0xc0ba); /* CS32 segment for 16 bit ESP fix */
++ 0, 0xfffff, 0xc09a); /* CS32 segment for 16 bit ESP fix */
+ set_seg((uint32_t *)(dt_table + (s->monitor_ss_null_sel >> 3)),
+ 0, 0, 0x40f2); /* substitute for null SS segment */
+ #else
+
+
+
diff --git a/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-02 b/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-02
new file mode 100644
index 000000000000..f9aca1d181e9
--- /dev/null
+++ b/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-02
@@ -0,0 +1,102 @@
+From: jan.kiszka@siemens.com (Jan Kiszka)
+Subject: [Qemu-devel] [PATCH 2/5] kqemu: i386: Reorder DS and ES on
+ exception stack
+Date: Fri, 29 May 2009 19:18:31 +0200
+Message-ID: <20090529171831.14265.74474.stgit@mchn012c.ww002.siemens.net>
+To: qemu-devel@nongnu.org
+
+This is a KQEMU upstream bug: In case the non-trivial paths of
+LOAD_SEG_CACHE in exception_return are taken for both DS and ES, the
+current code will break as it assumes to read from the monitor's DS in
+the restore code for ES. Fix this by swapping both segments on the stack
+so that ES is always restored before DS.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+
+ common/i386/monitor_asm.S | 16 ++++++++--------
+ common/kqemu_int.h | 6 +++---
+ 2 files changed, 11 insertions(+), 11 deletions(-)
+
+diff --git a/common/i386/monitor_asm.S b/common/i386/monitor_asm.S
+index 04f4258..e996553 100644
+Index: common/i386/monitor_asm.S
+--- a/common/i386/monitor_asm.S
++++ b/common/i386/monitor_asm.S
+@@ -214,8 +214,8 @@ __monitor_exception:
+ pushl %edx
+ pushl %ecx
+ pushl %eax
+- pushl %es
+ pushl %ds
++ pushl %es
+
+ /* compute the address of the monitor context */
+ call 1f
+@@ -260,17 +260,17 @@ exception_return:
+ cmpb $3, KQEMU_STATE_cpu_state_cpl(%ebx)
+ je normal_seg_load
+ popl %eax
+- LOAD_SEG_CACHE(%ds, R_DS, (11 * 4))
++ LOAD_SEG_CACHE(%es, R_ES, (11 * 4))
+ popl %eax
+- LOAD_SEG_CACHE(%es, R_ES, (10 * 4))
++ LOAD_SEG_CACHE(%ds, R_DS, (10 * 4))
+ jmp 2f
+ normal_seg_load:
+ #endif
+ 1:
+- popl %ds
++ popl %es
+ SEG_EXCEPTION(1b)
+ 1:
+- popl %es
++ popl %ds
+ SEG_EXCEPTION(1b)
+ 2:
+
+@@ -295,10 +295,10 @@ SEG_EXCEPTION(1b)
+
+ exception_return_to_monitor:
+ 1:
+- popl %ds
++ popl %es
+ SEG_EXCEPTION(1b)
+ 1:
+- popl %es
++ popl %ds
+ SEG_EXCEPTION(1b)
+ popl %eax
+ popl %ecx
+@@ -363,8 +363,8 @@ __monitor_interrupt:
+ pushl %edx
+ pushl %ecx
+ pushl %eax
+- pushl %es
+ pushl %ds
++ pushl %es
+
+ /* compute the address of the monitor context */
+ call 1f
+diff --git a/common/kqemu_int.h b/common/kqemu_int.h
+index f19f7ca..4b59cb3 100644
+Index: common/kqemu_int.h
+--- a/common/kqemu_int.h
++++ b/common/kqemu_int.h
+@@ -367,10 +367,10 @@ struct kqemu_exception_regs {
+ };
+ #else
+ struct kqemu_exception_regs {
+- uint16_t ds_sel; /* 0 */
+- uint16_t ds_sel_h;
+- uint16_t es_sel; /* 1 */
++ uint16_t es_sel; /* 0 */
+ uint16_t es_sel_h;
++ uint16_t ds_sel; /* 1 */
++ uint16_t ds_sel_h;
+ uint32_t eax; /* 2 */
+ uint32_t ecx;
+ uint32_t edx;
+
+
+
diff --git a/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-03 b/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-03
new file mode 100644
index 000000000000..f1e7b92d76e2
--- /dev/null
+++ b/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-03
@@ -0,0 +1,38 @@
+From: jan.kiszka@siemens.com (Jan Kiszka)
+Subject: [Qemu-devel] [PATCH 3/5] kqemu: Fix forbidden selector range change
+Date: Fri, 29 May 2009 19:18:31 +0200
+Message-ID: <20090529171831.14265.66049.stgit@mchn012c.ww002.siemens.net>
+To: qemu-devel@nongnu.org
+
+Do not bail out on LDT selectors that match the reserved monitor GDT
+selector range. At this chance, improve the related panic message.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+
+ common/interp.c | 7 +++++--
+ 1 files changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/common/interp.c b/common/interp.c
+index 088d2b2..4c042e9 100644
+Index: common/interp.c
+--- a/common/interp.c
++++ b/common/interp.c
+@@ -775,9 +775,12 @@ static void load_seg_desc(struct kqemu_state *s,
+ #ifdef DEBUG_SEG
+ monitor_log(s, "load_seg_desc: reg=%d sel=0x%04x\n", seg_reg, selector);
+ #endif
+- if (selector >= s->monitor_selector_base &&
++ if (!(selector & 0x4) && selector >= s->monitor_selector_base &&
+ selector <= (s->monitor_selector_base + MONITOR_SEL_RANGE)) {
+- monitor_panic(s, "Trying to load a reserved selector\n");
++ monitor_panic(s, "Trying to load a reserved selector "
++ "(reg=%d sel=0x%04x cs:ip=%04x:" FMT_lx ")\n",
++ seg_reg, selector, env->segs[R_CS].selector,
++ (unsigned long)env->eip);
+ }
+
+ if ((selector & 0xfffc) == 0) {
+
+
+
diff --git a/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-04 b/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-04
new file mode 100644
index 000000000000..57ab6d9f5cfd
--- /dev/null
+++ b/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-04
@@ -0,0 +1,108 @@
+From: jan.kiszka@siemens.com (Jan Kiszka)
+Subject: [Qemu-devel] [PATCH 4/5] kqemu: Implement verr/verw in the monitor
+ code interpreter
+Date: Fri, 29 May 2009 19:18:31 +0200
+Message-ID: <20090529171831.14265.57241.stgit@mchn012c.ww002.siemens.net>
+To: qemu-devel@nongnu.org
+
+This avoids user space for handling verr/verw via TCG.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+
+ common/interp.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 70 insertions(+), 1 deletions(-)
+
+diff --git a/common/interp.c b/common/interp.c
+index 4c042e9..4f93bc3 100644
+Index: common/interp.c
+--- a/common/interp.c
++++ b/common/interp.c
+@@ -1720,6 +1720,65 @@ void helper_lldt(struct kqemu_state *s, int selector)
+ env->ldt.selector = selector;
+ }
+
++static void helper_verr(struct kqemu_state *s, int selector)
++{
++ uint32_t e1, e2;
++ int rpl, dpl, cpl;
++
++ if ((selector & 0xfffc) == 0)
++ goto fail;
++ if (load_segment(s, &e1, &e2, selector) != 0)
++ goto fail;
++ if (!(e2 & DESC_S_MASK))
++ goto fail;
++ rpl = selector & 3;
++ dpl = (e2 >> DESC_DPL_SHIFT) & 3;
++ cpl = s->cpu_state.cpl;
++ if (e2 & DESC_CS_MASK) {
++ if (!(e2 & DESC_R_MASK))
++ goto fail;
++ if (!(e2 & DESC_C_MASK)) {
++ if (dpl < cpl || dpl < rpl)
++ goto fail;
++ }
++ } else {
++ if (dpl < cpl || dpl < rpl) {
++ fail:
++ set_reset_eflags(s, 0, CC_Z);
++ return;
++ }
++ }
++ set_reset_eflags(s, CC_Z, 0);
++}
++
++static void helper_verw(struct kqemu_state *s, int selector)
++{
++ uint32_t e1, e2;
++ int rpl, dpl, cpl;
++
++ if ((selector & 0xfffc) == 0)
++ goto fail;
++ if (load_segment(s, &e1, &e2, selector) != 0)
++ goto fail;
++ if (!(e2 & DESC_S_MASK))
++ goto fail;
++ rpl = selector & 3;
++ dpl = (e2 >> DESC_DPL_SHIFT) & 3;
++ cpl = s->cpu_state.cpl;
++ if (e2 & DESC_CS_MASK) {
++ goto fail;
++ } else {
++ if (dpl < cpl || dpl < rpl)
++ goto fail;
++ if (!(e2 & DESC_W_MASK)) {
++ fail:
++ set_reset_eflags(s, 0, CC_Z);
++ return;
++ }
++ }
++ set_reset_eflags(s, CC_Z, 0);
++}
++
+ static void helper_wrmsr(struct kqemu_state *s)
+ {
+ #ifdef __x86_64__
+@@ -4479,7 +4538,17 @@ QO( case OT_LONG | 8:\
+ case 5: /* verw */
+ if (!(s->cpu_state.cr0 & CR0_PE_MASK) || get_eflags_vm(s))
+ goto illegal_op;
+- raise_exception(s, KQEMU_RET_SOFTMMU);
++ if (mod == 3) {
++ rm = (modrm & 7) | REX_B(s);
++ val = get_regS(s, OT_WORD, rm) & 0xffff;
++ } else {
++ addr = get_modrm(s, modrm);
++ val = ldS(s, OT_WORD, addr);
++ }
++ if (op == 4)
++ helper_verr(s, val);
++ else
++ helper_verw(s, val);
+ break;
+ default:
+ goto illegal_op;
+
+
+
diff --git a/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-05 b/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-05
new file mode 100644
index 000000000000..23b2d17c9822
--- /dev/null
+++ b/emulators/kqemu-kmod-devel/files/extra-patch-jk-200905-05
@@ -0,0 +1,155 @@
+From: jan.kiszka@siemens.com (Jan Kiszka)
+Subject: [Qemu-devel] [PATCH 5/5] kqemu: Implement lar/lsl in the monitor
+ code interpreter
+Date: Fri, 29 May 2009 19:18:31 +0200
+Message-ID: <20090529171831.14265.17606.stgit@mchn012c.ww002.siemens.net>
+To: qemu-devel@nongnu.org
+
+This avoids user space for handling lar/lsl via TCG.
+
+Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+---
+
+ common/interp.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 109 insertions(+), 2 deletions(-)
+
+diff --git a/common/interp.c b/common/interp.c
+index 4f93bc3..577d666 100644
+Index: common/interp.c
+--- a/common/interp.c
++++ b/common/interp.c
+@@ -1720,6 +1720,93 @@ void helper_lldt(struct kqemu_state *s, int selector)
+ env->ldt.selector = selector;
+ }
+
++static int helper_lar(struct kqemu_state *s, int selector)
++{
++ uint32_t e1, e2;
++ int rpl, dpl, cpl, type;
++
++ if ((selector & 0xfffc) == 0)
++ goto fail;
++ if (load_segment(s, &e1, &e2, selector) != 0)
++ goto fail;
++ rpl = selector & 3;
++ dpl = (e2 >> DESC_DPL_SHIFT) & 3;
++ cpl = s->cpu_state.cpl;
++ if (e2 & DESC_S_MASK) {
++ if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
++ /* conforming */
++ } else {
++ if (dpl < cpl || dpl < rpl)
++ goto fail;
++ }
++ } else {
++ type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
++ switch(type) {
++ case 1:
++ case 2:
++ case 3:
++ case 4:
++ case 5:
++ case 9:
++ case 11:
++ case 12:
++ break;
++ default:
++ goto fail;
++ }
++ if (dpl < cpl || dpl < rpl) {
++ fail:
++ set_reset_eflags(s, 0, CC_Z);
++ return 0;
++ }
++ }
++ set_reset_eflags(s, CC_Z, 0);
++ return e2 & 0x00f0ff00;
++}
++
++static int helper_lsl(struct kqemu_state *s, int selector)
++{
++ unsigned int limit;
++ uint32_t e1, e2;
++ int rpl, dpl, cpl, type;
++
++ if ((selector & 0xfffc) == 0)
++ goto fail;
++ if (load_segment(s, &e1, &e2, selector) != 0)
++ goto fail;
++ rpl = selector & 3;
++ dpl = (e2 >> DESC_DPL_SHIFT) & 3;
++ cpl = s->cpu_state.cpl;
++ if (e2 & DESC_S_MASK) {
++ if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) {
++ /* conforming */
++ } else {
++ if (dpl < cpl || dpl < rpl)
++ goto fail;
++ }
++ } else {
++ type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
++ switch(type) {
++ case 1:
++ case 2:
++ case 3:
++ case 9:
++ case 11:
++ break;
++ default:
++ goto fail;
++ }
++ if (dpl < cpl || dpl < rpl) {
++ fail:
++ set_reset_eflags(s, 0, CC_Z);
++ return 0;
++ }
++ }
++ limit = get_seg_limit(e1, e2);
++ set_reset_eflags(s, CC_Z, 0);
++ return limit;
++}
++
+ static void helper_verr(struct kqemu_state *s, int selector)
+ {
+ uint32_t e1, e2;
+@@ -4616,6 +4703,28 @@ QO( case OT_LONG | 8:\
+ goto illegal_op;
+ }
+ goto insn_next;
++ LABEL(102) /* lar */
++ LABEL(103) /* lsl */
++ if (!(s->cpu_state.cr0 & CR0_PE_MASK) || get_eflags_vm(s))
++ goto illegal_op;
++ ot = s->dflag + OT_WORD;
++ modrm = ldub_code(s);
++ mod = (modrm >> 6);
++ if (mod == 3) {
++ rm = (modrm & 7) | REX_B(s);
++ val = get_regS(s, OT_WORD, rm) & 0xffff;
++ } else {
++ addr = get_modrm(s, modrm);
++ val = ldS(s, OT_WORD, addr);
++ }
++ rm = ((modrm >> 3) & 7) | REX_R(s);
++ if (b == 0x102)
++ val = helper_lar(s, val);
++ else
++ val = helper_lsl(s, val);
++ if (s->regs1.eflags & CC_Z)
++ set_regS(s, ot, rm, val);
++ goto insn_next;
+ LABEL(108) /* invd */
+ LABEL(109) /* wbinvd */
+ if (s->cpu_state.cpl != 0)
+@@ -5214,8 +5323,6 @@ QO( case OT_LONG | 8:\
+ LABEL(10b)
+ LABEL(10a)
+ LABEL(104)
+- LABEL(103)
+- LABEL(102)
+ LABEL(f1)
+ LABEL(e2)
+ LABEL(e1)
+
+
+