Bochs/bochs/patches/patch.msr
Bryce Denney 03cd6fa9ad - Zwane sent another version to the list at
Mon, 25 Mar 2002 11:47:38 +0200 (SAST)
  which should correct the compile problems when apic is disabled.
2002-03-25 15:29:17 +00:00

373 lines
9.8 KiB
Plaintext

Zwane sent another version to the list at
Mon, 25 Mar 2002 11:47:38 +0200 (SAST)
which should correct the compile problems when apic is disabled.
Updated so that it applies cleanly in cvs as of March 25. -Bryce
Notes by Bryce:
- normal configuration: one CPU and no APIC
FIXME: does not compile!
- normal SMP configuration: >1 CPU and APIC
compiles and works better than before. wli, mwane, bryce have been testing
in this config.
- test with one CPU and APIC
compiles ok
- test with BX_CPU_LEVEL<5: does it still compile?
tried --enable-cpu-level=4. compiles ok
compile warning:
proc_ctrl.cc: In method `void bx_cpu_c::WRMSR(struct BxInstruction_t *)':
proc_ctrl.cc:1273: warning: left shift count >= width of type
-----------------
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 /tmp/bochs-1.4.pre2/cpu/apic.cc bochs-1.4.pre2/cpu/apic.cc
--- /tmp/bochs-1.4.pre2/cpu/apic.cc Wed Oct 3 15:10:38 2001
+++ bochs-1.4.pre2/cpu/apic.cc Mon Mar 25 12:06:48 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:35 */
+ 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 /tmp/bochs-1.4.pre2/cpu/cpu.h bochs-1.4.pre2/cpu/cpu.h
--- /tmp/bochs-1.4.pre2/cpu/cpu.h Wed Oct 3 21:53:48 2001
+++ bochs-1.4.pre2/cpu/cpu.h Mon Mar 25 12:08:32 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 */
@@ -521,6 +567,8 @@
APIC_TYPE_LOCAL_APIC
} bx_apic_type_t;
+#define APIC_BASE_ADDR 0xfee00000 // default APIC address
+
#if BX_SUPPORT_APIC
class bx_generic_apic_c : public logfunctions {
protected:
@@ -577,7 +625,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 +663,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 +801,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 +817,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 /tmp/bochs-1.4.pre2/cpu/init.cc bochs-1.4.pre2/cpu/init.cc
--- /tmp/bochs-1.4.pre2/cpu/init.cc Wed Oct 3 15:10:38 2001
+++ bochs-1.4.pre2/cpu/init.cc Mon Mar 25 12:06:48 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 /tmp/bochs-1.4.pre2/cpu/proc_ctrl.cc bochs-1.4.pre2/cpu/proc_ctrl.cc
--- /tmp/bochs-1.4.pre2/cpu/proc_ctrl.cc Sun Nov 18 18:32:40 2001
+++ bochs-1.4.pre2/cpu/proc_ctrl.cc Mon Mar 25 12:06:48 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
--
rants : http://function.linuxpower.ca
_______________________________________________
bochs-developers mailing list
bochs-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bochs-developers