Bochs/bochs/patches/patch.sysenterexit-mrieker

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_SREG_CS].selector.value = BX_CPU_THIS_PTR sysenter_cs_msr;
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].selector.index = BX_CPU_THIS_PTR sysenter_cs_msr >> 3;
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].selector.ti = (BX_CPU_THIS_PTR sysenter_cs_msr >> 2) & 1;
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].selector.rpl = 0;
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.executable = 1; // code segment
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.c_ed = 0; // non-conforming
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.r_w = 1; // readable
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.a = 1; // accessed
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.base = 0; // base address
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.limit = 0xFFFF; // segment limit
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; // scaled segment limit
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.g = 1; // 4k granularity
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.d_b = 1; // 32-bit mode
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.avl = 0; // available for use by system
+
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].selector.value = BX_CPU_THIS_PTR sysenter_cs_msr + 8;
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].selector.index = (BX_CPU_THIS_PTR sysenter_cs_msr + 8) >> 3;
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].selector.ti = (BX_CPU_THIS_PTR sysenter_cs_msr >> 2) & 1;
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].selector.rpl = 0;
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.executable = 0; // data segment
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.c_ed = 0; // expand-up
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.r_w = 1; // writeable
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.a = 1; // accessed
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.base = 0; // base address
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.limit = 0xFFFF; // segment limit
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.limit_scaled = 0xFFFFFFFF; // scaled segment limit
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.g = 1; // 4k granularity
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.d_b = 1; // 32-bit mode
+ BX_CPU_THIS_PTR sregs[BX_SREG_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_SREG_CS].selector.value = (BX_CPU_THIS_PTR sysenter_cs_msr + 16) | 3;
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].selector.index = (BX_CPU_THIS_PTR sysenter_cs_msr + 16) >> 3;
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].selector.ti = (BX_CPU_THIS_PTR sysenter_cs_msr >> 2) & 1;
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].selector.rpl = 3;
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.executable = 1; // code segment
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.c_ed = 0; // non-conforming
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.r_w = 1; // readable
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.a = 1; // accessed
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.base = 0; // base address
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.limit = 0xFFFF; // segment limit
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; // scaled segment limit
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.g = 1; // 4k granularity
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.d_b = 1; // 32-bit mode
+ BX_CPU_THIS_PTR sregs[BX_SREG_CS].cache.u.segment.avl = 0; // available for use by system
+
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].selector.value = (BX_CPU_THIS_PTR sysenter_cs_msr + 24) | 3;
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].selector.index = (BX_CPU_THIS_PTR sysenter_cs_msr + 24) >> 3;
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].selector.ti = (BX_CPU_THIS_PTR sysenter_cs_msr >> 2) & 1;
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].selector.rpl = 3;
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.executable = 0; // data segment
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.c_ed = 0; // expand-up
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.r_w = 1; // writeable
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.a = 1; // accessed
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.base = 0; // base address
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.limit = 0xFFFF; // segment limit
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.limit_scaled = 0xFFFFFFFF; // scaled segment limit
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.g = 1; // 4k granularity
+ BX_CPU_THIS_PTR sregs[BX_SREG_SS].cache.u.segment.d_b = 1; // 32-bit mode
+ BX_CPU_THIS_PTR sregs[BX_SREG_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