Bochs/bochs/patches/patch.msr
Bryce Denney bc8f4eb0f0 - patch from Zwane Mwaikambo <zwane@linux.realnet.co.sz>
that adds partial MSR support.  I plan to add this after 1.4 is released.
2002-03-15 05:37:30 +00:00

346 lines
9.0 KiB
Plaintext

I've managed to boot linux 2.2.21-pre1 with this patch, i was having
problems before when it tried to enable the APIC via the MSR registers.
Now i just need to fix the TSC skew problems (i managed to workaround it
by doing the fixups in the linux kernel, but gonna do it via Bochs this
time).
Cheers,
Zwane Mwaikambo
PS this is just the infrastructure, i haven't done all the registers, most
notably the MTRR stuff.
diff -ur bochs-1.3/cpu/apic.cc /build/source/bochs-1.3/cpu/apic.cc
--- bochs-1.3/cpu/apic.cc Wed Oct 3 15:10:37 2001
+++ /build/source/bochs-1.3/cpu/apic.cc Mon Mar 11 08:00:36 2002
@@ -27,6 +27,14 @@
{
}
+void bx_local_apic_c::update_msr_apicbase(Bit32u newbase)
+{
+ Bit64u val64;
+ val64 = newbase << 12; /* push the APIC base address to bits 12:31 */
+ val64 += cpu->msr.apicbase & 0x0900; /* don't modify other apicbase or reserved bits */
+ cpu->msr.apicbase = val64;
+}
+
void bx_generic_apic_c::set_base (Bit32u newbase)
{
BX_INFO(("relocate APIC id=%d to %8x", id, newbase));
@@ -247,7 +255,8 @@
BX_INFO(("local apic in %s initializing",
(cpu && cpu->name) ? cpu->name : "?"));
// default address for a local APIC, can be moved
- base_addr = 0xfee00000;
+ base_addr = APIC_BASE_ADDR;
+ update_msr_apicbase(base_addr);
err_status = 0;
log_dest = 0;
dest_format = 0xff;
diff -ur bochs-1.3/cpu/cpu.h /build/source/bochs-1.3/cpu/cpu.h
--- bochs-1.3/cpu/cpu.h Wed Oct 3 21:53:48 2001
+++ /build/source/bochs-1.3/cpu/cpu.h Sun Mar 10 19:07:40 2002
@@ -195,9 +195,43 @@
#define BX_MF_EXCEPTION 16
#define BX_AC_EXCEPTION 17
-
-
-
+/* MSR registers */
+#define BX_MSR_P5_MC_ADDR 0x0000
+#define BX_MSR_MC_TYPE 0x0001
+#define BX_MSR_TSC 0x0010
+#define BX_MSR_CESR 0x0011
+#define BX_MSR_CTR0 0x0012
+#define BX_MSR_CTR1 0x0013
+#define BX_MSR_APICBASE 0x001b
+#define BX_MSR_EBL_CR_POWERON 0x002a
+#define BX_MSR_TEST_CTL 0x0033
+#define BX_MSR_BIOS_UPDT_TRIG 0x0079
+#define BX_MSR_BBL_CR_D0 0x0088
+#define BX_MSR_BBL_CR_D1 0x0089
+#define BX_MSR_BBL_CR_D2 0x008a
+#define BX_MSR_BBL_CR_D3 0x008b /* = BIOS_SIGN */
+#define BX_MSR_PERFCTR0 0x00c1
+#define BX_MSR_PERFCTR1 0x00c2
+#define BX_MSR_MTRRCAP 0x00fe
+#define BX_MSR_BBL_CR_ADDR 0x0116
+#define BX_MSR_BBL_DECC 0x0118
+#define BX_MSR_BBL_CR_CTL 0x0119
+#define BX_MSR_BBL_CR_TRIG 0x011a
+#define BX_MSR_BBL_CR_BUSY 0x011b
+#define BX_MSR_BBL_CR_CTL3 0x011e
+#define BX_MSR_MCG_CAP 0x0179
+#define BX_MSR_MCG_STATUS 0x017a
+#define BX_MSR_MCG_CTL 0x017b
+#define BX_MSR_EVNTSEL0 0x0186
+#define BX_MSR_EVNTSEL1 0x0187
+#define BX_MSR_DEBUGCTLMSR 0x01d9
+#define BX_MSR_LASTBRANCHFROMIP 0x01db
+#define BX_MSR_LASTBRANCHTOIP 0x01dc
+#define BX_MSR_LASTINTOIP 0x01dd
+#define BX_MSR_ROB_CR_BKUPTMPDR6 0x01e0
+#define BX_MSR_MTRRPHYSBASE0 0x0200
+#define BX_MSR_MTRRPHYSMASK0 0x0201
+#define BX_MSR_MTRRPHYSBASE1 0x0202
typedef struct {
/* 31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16
@@ -286,6 +320,18 @@
} bx_cr0_t;
#endif
+#if BX_CPU_LEVEL >= 5
+typedef struct {
+ Bit8u p5_mc_addr;
+ Bit8u p5_mc_type;
+ Bit8u tsc;
+ Bit8u cesr;
+ Bit8u ctr0;
+ Bit8u ctr1;
+ Bit64u apicbase;
+ /* TODO finish of the others */
+ } bx_regs_msr_t;
+#endif
typedef struct { /* bx_selector_t */
Bit16u value; /* the 16bit value of the selector */
@@ -528,6 +574,7 @@
Bit8u id;
#define APIC_UNKNOWN_ID 0xff
#define APIC_VERSION_ID 0x00170011 // same version as 82093 IOAPIC
+#define APIC_BASE_ADDR 0xfee00000 // default APIC address
public:
bx_generic_apic_c ();
virtual ~bx_generic_apic_c ();
@@ -577,7 +624,6 @@
Bit32u timer_initial, timer_current, timer_divconf;
Boolean timer_active; // internal state, not accessible from bus
Bit32u timer_divide_counter, timer_divide_factor;
- Bit32u apic_base_msr;
Bit32u icr_high, icr_low;
Bit32u err_status;
#define APIC_ERR_ILLEGAL_ADDR 0x80
@@ -616,6 +662,7 @@
Bit8u get_apr ();
void periodic (Bit32u usec_delta);
void set_divide_configuration (Bit32u value);
+ virtual void update_msr_apicbase(Bit32u newaddr);
};
#define APIC_MAX_ID 16
@@ -753,6 +800,10 @@
Bit32u cr4;
#endif
+#if BX_CPU_LEVEL >= 5
+ bx_regs_msr_t msr;
+#endif
+
// pointer to the address space that this processor uses.
BX_MEM_C *mem;
@@ -765,6 +816,8 @@
volatile Boolean async_event;
volatile Boolean INTR;
+ /* wether this CPU is the BSP always set for UP */
+ Boolean bsp;
// for accessing registers by index number
Bit16u *_16bit_base_reg[8];
Bit16u *_16bit_index_reg[8];
diff -ur bochs-1.3/cpu/init.cc /build/source/bochs-1.3/cpu/init.cc
--- bochs-1.3/cpu/init.cc Wed Oct 3 15:10:37 2001
+++ /build/source/bochs-1.3/cpu/init.cc Mon Mar 11 08:13:51 2002
@@ -554,7 +554,11 @@
BX_CPU_THIS_PTR cr4 = 0;
#endif
-
+/* initialise MSR registers to defaults */
+#if BX_CPU_LEVEL >= 5
+ /* APIC Address, APIC enabled and BSP is default, we'll fill in the rest later */
+ BX_CPU_THIS_PTR msr.apicbase = (APIC_BASE_ADDR << 12) + 0x900;
+#endif
BX_CPU_THIS_PTR EXT = 0;
//BX_INTR = 0;
@@ -593,9 +597,13 @@
if (BX_BOOTSTRAP_PROCESSOR == apic_id)
{
// boot normally
+ BX_CPU_THIS_PTR bsp = 1;
+ BX_CPU_THIS_PTR msr.apicbase |= 0x0100; /* set bit 8 BSP */
BX_INFO(("CPU[%d] is the bootstrap processor", apic_id));
} else {
// it's an application processor, halt until IPI is heard.
+ BX_CPU_THIS_PTR bsp = 0;
+ BX_CPU_THIS_PTR msr.apicbase &= ~0x0100; /* clear bit 8 BSP */
BX_INFO(("CPU[%d] is an application processor. Halting until IPI.", apic_id));
debug_trap |= 0x80000000;
async_event = 1;
diff -ur bochs-1.3/cpu/proc_ctrl.cc /build/source/bochs-1.3/cpu/proc_ctrl.cc
--- bochs-1.3/cpu/proc_ctrl.cc Sun Nov 18 18:32:40 2001
+++ /build/source/bochs-1.3/cpu/proc_ctrl.cc Mon Mar 11 08:07:35 2002
@@ -1147,23 +1147,143 @@
BX_CPU_C::RDMSR(BxInstruction_t *i)
{
#if BX_CPU_LEVEL >= 5
- BX_ERROR(("RDMSR: not implemented yet"));
- UndefinedOpcode(i);
+ invalidate_prefetch_q();
+
+ if (v8086_mode()) {
+ BX_INFO(("RDMSR: Invalid whilst in virtual 8086 mode"));
+ goto do_exception;
+ }
+
+ if (CPL!= 0) {
+ BX_INFO(("RDMSR: CPL!= 0"));
+ goto do_exception;
+ }
+
+ /* We have the requested MSR register in ECX */
+ switch(ECX) {
+#if BX_CPU_LEVEL == 5
+ /* The following registers are defined for Pentium only */
+ case BX_MSR_P5_MC_ADDR:
+ case BX_MSR_MC_TYPE:
+ /* TODO */
+ return;
+
+ case BX_MSR_TSC:
+ RDTSC(i);
+ return;
+
+ case BX_MSR_CESR:
+ /* TODO */
+ return;
#else
- UndefinedOpcode(i);
-#endif
+ /* These are noops on i686... */
+ case BX_MSR_P5_MC_ADDR:
+ case BX_MSR_MC_TYPE:
+ /* do nothing */
+ return;
+
+ case BX_MSR_TSC:
+ RDTSC(i);
+ return;
+
+ /* ... And these cause an exception on i686 */
+ case BX_MSR_CESR:
+ case BX_MSR_CTR0:
+ case BX_MSR_CTR1:
+ goto do_exception;
+#endif /* BX_CPU_LEVEL == 5 */
+
+ /* MSR_APICBASE
+ 0:7 Reserved
+ 8 This is set if its the BSP
+ 9:10 Reserved
+ 11 APIC Global Enable bit (1=enabled 0=disabled)
+ 12:35 APIC Base Address
+ 36:63 Reserved
+ */
+ case BX_MSR_APICBASE:
+ /* we return low 32 bits in EAX, and high in EDX */
+ EAX = BX_CPU_THIS_PTR msr.apicbase & 0xff;
+ EDX = BX_CPU_THIS_PTR msr.apicbase >> 32;
+ BX_INFO(("RDMSR: Read %08x:%08x from MSR_APICBASE", EDX, EAX));
+ return;
+
+ default:
+ BX_INFO(("RDMSR: Unknown register!"));
+ goto do_exception;
+
+ }
+#endif /* BX_CPU_LEVEL >= 5 */
+
+do_exception:
+ exception(BX_GP_EXCEPTION, 0, 0);
}
void
BX_CPU_C::WRMSR(BxInstruction_t *i)
{
#if BX_CPU_LEVEL >= 5
- invalidate_prefetch_q();
+ invalidate_prefetch_q();
- BX_PANIC(( "WRMSR: not implemented yet"));
+ if (v8086_mode()) {
+ BX_INFO(("WRMSR: Invalid whilst in virtual 8086 mode"));
+ goto do_exception;
+ }
+
+ if (CPL!= 0) {
+ BX_INFO(("WDMSR: CPL!= 0"));
+ goto do_exception;
+ }
+
+ /* ECX has the MSR to write to */
+ switch(ECX) {
+#if BX_CPU_LEVEL == 5
+ /* The following registers are defined for Pentium only */
+ case BX_MSR_P5_MC_ADDR:
+ case BX_MSR_MC_TYPE:
+ case BX_MSR_TSC:
+ case BX_MSR_CESR:
+ /* TODO */
+ return;
#else
- UndefinedOpcode(i);
-#endif
+ /* These are noops on i686... */
+ case BX_MSR_P5_MC_ADDR:
+ case BX_MSR_MC_TYPE:
+ case BX_MSR_TSC:
+ /* do nothing */
+ return;
+
+ /* ... And these cause an exception on i686 */
+ case BX_MSR_CESR:
+ case BX_MSR_CTR0:
+ case BX_MSR_CTR1:
+ goto do_exception;
+#endif /* BX_CPU_LEVEL == 5 */
+
+ /* MSR_APICBASE
+ 0:7 Reserved
+ 8 This is set if its the BSP
+ 9:10 Reserved
+ 11 APIC Global Enable bit (1=enabled 0=disabled)
+ 12:35 APIC Base Address
+ 36:63 Reserved
+ */
+
+ case BX_MSR_APICBASE:
+ BX_CPU_THIS_PTR msr.apicbase = (EDX << 32) + EAX;
+ BX_INFO(("WRMSR: wrote %08x:%08x to MSR_APICBASE", EDX, EAX));
+ return;
+
+ default:
+ BX_INFO(("WRMSR: Unknown register!"));
+ goto do_exception;
+
+ }
+#endif /* BX_CPU_LEVEL >= 5 */
+
+do_exception:
+ exception(BX_GP_EXCEPTION, 0, 0);
+
}
#if BX_X86_DEBUGGER
_______________________________________________
bochs-developers mailing list
bochs-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bochs-developers