335 lines
13 KiB
Plaintext
335 lines
13 KiB
Plaintext
----------------------------------------------------------------------
|
|
Patch name: patch.sysenterexit-mrieker
|
|
Author: Mike Rieker
|
|
Date: 27 June 2002
|
|
|
|
Detailed description:
|
|
|
|
This patch adds sysenter/sysexit functions support
|
|
for cpu >= Pentium-Pro
|
|
For now, support must be explicitely enabled in config.h
|
|
#define BX_SUPPORT_SYSENTEREXIT 1
|
|
|
|
Patch was created with:
|
|
cvs diff -u
|
|
Apply patch to what version:
|
|
cvs checked out on 27 June 2002
|
|
Instructions:
|
|
To patch, go to main bochs directory.
|
|
Type "patch -p0 < THIS_PATCH_FILE".
|
|
----------------------------------------------------------------------
|
|
Index: config.h.in
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/config.h.in,v
|
|
retrieving revision 1.50
|
|
diff -u -r1.50 config.h.in
|
|
--- config.h.in 5 Jun 2002 03:59:30 -0000 1.50
|
|
+++ config.h.in 27 Jun 2002 21:27:40 -0000
|
|
@@ -189,6 +189,13 @@
|
|
|
|
#define BX_SUPPORT_V8086_MODE 1
|
|
|
|
+// SYSENTER / SYSEXIT support
|
|
+#define BX_SUPPORT_SYSENTEREXIT 0
|
|
+
|
|
+#if (BX_CPU_LEVEL<6 && BX_SUPPORT_SYSENTEREXIT)
|
|
+#error SYSENTER/SYSEXIT only supported with CPU_LEVEL >= 6
|
|
+#endif
|
|
+
|
|
// Support shadowing of ROM from C0000 to FFFFF.
|
|
// This allows that region to be written to.
|
|
#define BX_SHADOW_RAM 0
|
|
Index: cpu/cpu.h
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/cpu/cpu.h,v
|
|
retrieving revision 1.22
|
|
diff -u -r1.22 cpu.h
|
|
--- cpu/cpu.h 5 Jun 2002 21:51:30 -0000 1.22
|
|
+++ cpu/cpu.h 27 Jun 2002 21:27:47 -0000
|
|
@@ -219,6 +219,11 @@
|
|
#define BX_MSR_BBL_CR_TRIG 0x011a
|
|
#define BX_MSR_BBL_CR_BUSY 0x011b
|
|
#define BX_MSR_BBL_CR_CTL3 0x011e
|
|
+#if BX_SUPPORT_SYSENTEREXIT
|
|
+# define BX_MSR_SYSENTER_CS 0x0174
|
|
+# define BX_MSR_SYSENTER_ESP 0x0175
|
|
+# define BX_MSR_SYSENTER_EIP 0x0176
|
|
+#endif
|
|
#define BX_MSR_MCG_CAP 0x0179
|
|
#define BX_MSR_MCG_STATUS 0x017a
|
|
#define BX_MSR_MCG_CTL 0x017b
|
|
@@ -276,7 +281,6 @@
|
|
#endif
|
|
} bx_flags_reg_t;
|
|
|
|
-
|
|
#if BX_CPU_LEVEL >= 2
|
|
typedef struct {
|
|
Bit32u val32; // 32bit value of register
|
|
@@ -581,6 +585,7 @@
|
|
virtual ~bx_generic_apic_c ();
|
|
virtual void init ();
|
|
virtual void hwreset () { }
|
|
+ virtual BX_CPU_C *get_cpu (void);
|
|
Bit32u get_base (void) { return base_addr; }
|
|
void set_base (Bit32u newbase);
|
|
void set_id (Bit8u newid);
|
|
@@ -641,7 +646,7 @@
|
|
BX_CPU_C *cpu;
|
|
virtual void hwreset ();
|
|
virtual void init ();
|
|
- BX_CPU_C *get_cpu (Bit8u id);
|
|
+ virtual BX_CPU_C *get_cpu (void);
|
|
void set_id (Bit8u newid); // redefine to set cpu->name
|
|
virtual char *get_name();
|
|
virtual void write (Bit32u addr, Bit32u *data, unsigned len);
|
|
@@ -820,6 +825,7 @@
|
|
volatile Boolean async_event;
|
|
volatile Boolean INTR;
|
|
volatile Boolean kill_bochs_request;
|
|
+ volatile Boolean nmi_queued;
|
|
|
|
/* wether this CPU is the BSP always set for UP */
|
|
Boolean bsp;
|
|
@@ -871,6 +877,13 @@
|
|
bx_guard_found_t guard_found;
|
|
#endif
|
|
|
|
+ // SYSENTER/SYSEXIT instruction msr's
|
|
+#if BX_SUPPORT_SYSENTEREXIT
|
|
+ Bit32u sysenter_cs_msr;
|
|
+ Bit32u sysenter_esp_msr;
|
|
+ Bit32u sysenter_eip_msr;
|
|
+#endif
|
|
+
|
|
// for paging
|
|
#if BX_USE_TLB
|
|
struct {
|
|
@@ -1349,6 +1362,8 @@
|
|
BX_SMF void WRMSR(BxInstruction_t *);
|
|
BX_SMF void RDTSC(BxInstruction_t *);
|
|
BX_SMF void RDMSR(BxInstruction_t *);
|
|
+ BX_SMF void SYSENTER(BxInstruction_t *);
|
|
+ BX_SMF void SYSEXIT(BxInstruction_t *);
|
|
BX_SMF void SetCR0(Bit32u val_32);
|
|
BX_SMF void dynamic_translate(void);
|
|
BX_SMF void dynamic_init(void);
|
|
Index: cpu/fetchdecode.cc
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/cpu/fetchdecode.cc,v
|
|
retrieving revision 1.7
|
|
diff -u -r1.7 fetchdecode.cc
|
|
--- cpu/fetchdecode.cc 3 Oct 2001 13:10:37 -0000 1.7
|
|
+++ cpu/fetchdecode.cc 27 Jun 2002 21:27:48 -0000
|
|
@@ -1174,8 +1174,13 @@
|
|
/* 0F 31 */ { 0, &BX_CPU_C::RDTSC },
|
|
/* 0F 32 */ { 0, &BX_CPU_C::RDMSR },
|
|
/* 0F 33 */ { 0, &BX_CPU_C::BxError },
|
|
+#if BX_SUPPORT_SYSENTEREXIT
|
|
+ /* 0F 34 */ { 0, &BX_CPU_C::SYSENTER },
|
|
+ /* 0F 35 */ { 0, &BX_CPU_C::SYSEXIT },
|
|
+#else
|
|
/* 0F 34 */ { 0, &BX_CPU_C::BxError },
|
|
/* 0F 35 */ { 0, &BX_CPU_C::BxError },
|
|
+#endif
|
|
/* 0F 36 */ { 0, &BX_CPU_C::BxError },
|
|
/* 0F 37 */ { 0, &BX_CPU_C::BxError },
|
|
/* 0F 38 */ { 0, &BX_CPU_C::BxError },
|
|
Index: cpu/proc_ctrl.cc
|
|
===================================================================
|
|
RCS file: /cvsroot/bochs/bochs/cpu/proc_ctrl.cc,v
|
|
retrieving revision 1.22
|
|
diff -u -r1.22 proc_ctrl.cc
|
|
--- cpu/proc_ctrl.cc 19 Jun 2002 15:49:07 -0000 1.22
|
|
+++ cpu/proc_ctrl.cc 27 Jun 2002 21:27:48 -0000
|
|
@@ -968,8 +968,8 @@
|
|
// ECX: vendor ID string
|
|
EAX = 1; // 486 or pentium
|
|
EBX = 0x756e6547; // "Genu"
|
|
- EDX = 0x49656e69; // "ineI"
|
|
- ECX = 0x6c65746e; // "ntel"
|
|
+ EDX = 0x42656e69; // "ineB"
|
|
+ ECX = 0x7368636f; // "ochs"
|
|
break;
|
|
|
|
case 1:
|
|
@@ -1030,16 +1030,20 @@
|
|
model = 1; // Pentium Pro
|
|
stepping = 3; // ???
|
|
features |= (1<<4); // implement TSC
|
|
+ features |= (1<<3); // implement 4M pages
|
|
# if BX_SUPPORT_APIC
|
|
features |= (1<<9); // APIC on chip
|
|
# endif
|
|
# if BX_SUPPORT_FPU
|
|
features |= 0x01; // has FPU
|
|
# endif
|
|
+# if BX_SUPPORT_SYSENTEREXIT
|
|
+ features |= (1<<11); // SYSENTER/SYSEXIT
|
|
+# endif
|
|
+
|
|
#else
|
|
BX_PANIC(("CPUID: not implemented for > 6"));
|
|
-#endif
|
|
- features |= 8; // support page-size extension (4m pages)
|
|
+#endif
|
|
|
|
EAX = (family <<8) | (model<<4) | stepping;
|
|
EBX = ECX = 0; // reserved
|
|
@@ -1160,6 +1164,11 @@
|
|
|
|
/* We have the requested MSR register in ECX */
|
|
switch(ECX) {
|
|
+#if BX_SUPPORT_SYSENTEREXIT
|
|
+ case BX_MSR_SYSENTER_CS: { EAX = BX_CPU_THIS_PTR sysenter_cs_msr; EDX = 0; return; }
|
|
+ case BX_MSR_SYSENTER_ESP: { EAX = BX_CPU_THIS_PTR sysenter_esp_msr; EDX = 0; return; }
|
|
+ case BX_MSR_SYSENTER_EIP: { EAX = BX_CPU_THIS_PTR sysenter_eip_msr; EDX = 0; return; }
|
|
+#endif
|
|
#if BX_CPU_LEVEL == 5
|
|
/* The following registers are defined for Pentium only */
|
|
case BX_MSR_P5_MC_ADDR:
|
|
@@ -1236,6 +1245,15 @@
|
|
|
|
/* ECX has the MSR to write to */
|
|
switch(ECX) {
|
|
+#if BX_SUPPORT_SYSENTEREXIT
|
|
+ case BX_MSR_SYSENTER_CS: {
|
|
+ if (EAX & 3) BX_PANIC (("writing sysenter_cs_msr with non-kernel mode selector %X", EAX)); // not a bug according to book
|
|
+ BX_CPU_THIS_PTR sysenter_cs_msr = EAX; // ... but very stOOpid
|
|
+ return;
|
|
+ }
|
|
+ case BX_MSR_SYSENTER_ESP: { BX_CPU_THIS_PTR sysenter_esp_msr = EAX; return; }
|
|
+ case BX_MSR_SYSENTER_EIP: { BX_CPU_THIS_PTR sysenter_eip_msr = EAX; return; }
|
|
+#endif
|
|
#if BX_CPU_LEVEL == 5
|
|
/* The following registers are defined for Pentium only */
|
|
case BX_MSR_P5_MC_ADDR:
|
|
@@ -1283,6 +1301,127 @@
|
|
do_exception:
|
|
exception(BX_GP_EXCEPTION, 0, 0);
|
|
|
|
+}
|
|
+
|
|
+ void
|
|
+BX_CPU_C::SYSENTER (BxInstruction_t *i)
|
|
+{
|
|
+#if BX_SUPPORT_SYSENTEREXIT
|
|
+ if (!protected_mode ()) {
|
|
+ BX_INFO (("sysenter not from protected mode"));
|
|
+ exception (BX_GP_EXCEPTION, 0, 0);
|
|
+ return;
|
|
+ }
|
|
+ if (BX_CPU_THIS_PTR sysenter_cs_msr == 0) {
|
|
+ BX_INFO (("sysenter with zero sysenter_cs_msr"));
|
|
+ exception (BX_GP_EXCEPTION, 0, 0);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ invalidate_prefetch_q ();
|
|
+
|
|
+ BX_CPU_THIS_PTR eflags.vm = 0; // do this just like the book says to do
|
|
+ BX_CPU_THIS_PTR eflags.if_ = 0;
|
|
+ BX_CPU_THIS_PTR eflags.rf = 0;
|
|
+
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value = BX_CPU_THIS_PTR sysenter_cs_msr;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.index = BX_CPU_THIS_PTR sysenter_cs_msr >> 3;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.ti = (BX_CPU_THIS_PTR sysenter_cs_msr >> 2) & 1;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl = 0;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = 1; // code segment
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed = 0; // non-conforming
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w = 1; // readable
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.a = 1; // accessed
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; // base address
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xFFFF; // segment limit
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; // scaled segment limit
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; // 4k granularity
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1; // 32-bit mode
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; // available for use by system
|
|
+
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value = BX_CPU_THIS_PTR sysenter_cs_msr + 8;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.index = (BX_CPU_THIS_PTR sysenter_cs_msr + 8) >> 3;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.ti = (BX_CPU_THIS_PTR sysenter_cs_msr >> 2) & 1;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.rpl = 0;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.executable = 0; // data segment
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.c_ed = 0; // expand-up
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.r_w = 1; // writeable
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.a = 1; // accessed
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base = 0; // base address
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit = 0xFFFF; // segment limit
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled = 0xFFFFFFFF; // scaled segment limit
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.g = 1; // 4k granularity
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b = 1; // 32-bit mode
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.avl = 0; // available for use by system
|
|
+
|
|
+ // BX_INFO (("sysenter: old eip %X, esp %x, new eip %x, esp %X, edx %X", BX_CPU_THIS_PTR prev_eip, ESP, BX_CPU_THIS_PTR sysenter_eip_msr, BX_CPU_THIS_PTR sysenter_esp_msr, EDX));
|
|
+
|
|
+ ESP = BX_CPU_THIS_PTR sysenter_esp_msr;
|
|
+ EIP = BX_CPU_THIS_PTR sysenter_eip_msr;
|
|
+#else
|
|
+ UndefinedOpcode (i);
|
|
+#endif
|
|
+}
|
|
+
|
|
+ void
|
|
+BX_CPU_C::SYSEXIT (BxInstruction_t *i)
|
|
+{
|
|
+#if BX_SUPPORT_SYSENTEREXIT
|
|
+ if (!protected_mode ()) {
|
|
+ BX_INFO (("sysexit not from protected mode"));
|
|
+ exception (BX_GP_EXCEPTION, 0, 0);
|
|
+ return;
|
|
+ }
|
|
+ if (BX_CPU_THIS_PTR sysenter_cs_msr == 0) {
|
|
+ BX_INFO (("sysexit with zero sysenter_cs_msr"));
|
|
+ exception (BX_GP_EXCEPTION, 0, 0);
|
|
+ return;
|
|
+ }
|
|
+ if (CPL != 0) {
|
|
+ BX_INFO (("sysexit at non-zero cpl %u", CPL));
|
|
+ exception (BX_GP_EXCEPTION, 0, 0);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ invalidate_prefetch_q ();
|
|
+
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value = (BX_CPU_THIS_PTR sysenter_cs_msr + 16) | 3;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.index = (BX_CPU_THIS_PTR sysenter_cs_msr + 16) >> 3;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.ti = (BX_CPU_THIS_PTR sysenter_cs_msr >> 2) & 1;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl = 3;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.executable = 1; // code segment
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.c_ed = 0; // non-conforming
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.r_w = 1; // readable
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.a = 1; // accessed
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; // base address
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xFFFF; // segment limit
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; // scaled segment limit
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; // 4k granularity
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1; // 32-bit mode
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; // available for use by system
|
|
+
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value = (BX_CPU_THIS_PTR sysenter_cs_msr + 24) | 3;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.index = (BX_CPU_THIS_PTR sysenter_cs_msr + 24) >> 3;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.ti = (BX_CPU_THIS_PTR sysenter_cs_msr >> 2) & 1;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.rpl = 3;
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.executable = 0; // data segment
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.c_ed = 0; // expand-up
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.r_w = 1; // writeable
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.a = 1; // accessed
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base = 0; // base address
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit = 0xFFFF; // segment limit
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled = 0xFFFFFFFF; // scaled segment limit
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.g = 1; // 4k granularity
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b = 1; // 32-bit mode
|
|
+ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.avl = 0; // available for use by system
|
|
+
|
|
+ // BX_INFO (("sysexit: old eip %X, esp %x, new eip %x, esp %X, eax %X", BX_CPU_THIS_PTR prev_eip, ESP, EDX, ECX, EAX));
|
|
+
|
|
+ ESP = ECX;
|
|
+ EIP = EDX;
|
|
+#else
|
|
+ UndefinedOpcode (i);
|
|
+#endif
|
|
}
|
|
|
|
#if BX_X86_DEBUGGER
|