APIC & AMD64 [SOLVED]
Posted: Mon Apr 30, 2007 3:56 pm
Hi !!!
I was making a little OS to test some recently acquired skills but I got stucked. The problem is this:
First I change the mapping of the APIC through the IA32_APIC_BASE MSR to something like 0x28000, then I read some APIC parameters ( Local APIC ID, Max LVT, APIC Version ) from 0xC0082020 & 0xC0082020 ( I use paging and I have a whole GB from 0xC0000000 to the end ). In Bochs and VMWare works great, but when I really boot into this little application ( I mean like a really OS ) it gets totally frozen. First I thought it could be something wrong with the video, so, I tried to make it triple fault by loading the GDT with a wrong address, using floating point math and making a page fault but it didn't work... I don't know what's going on... I'm going mad !!!
Here is a little of code:
The code from "Enable APIC" to "Thermal Sensor" wasn't there originally, but it didn't make any difference anyway. I've tracked down the problem to the reading of APIC Version & Local APIC ID.
Also, I've found this on the Linux kernel:
That means I have no APIC Version? But what about the Local APIC ID? OK... I can use CPUID in place... but... I've read AMD's "BIOS & Kernel developers guide" and I think it should work. At least the APIC Register is there, maybe is an old version ( 0x10 vs 0x14 I think... ) but it should work...
Thanks so much for reading !!!
And sorry for my English ( specially the verbs... )
I was making a little OS to test some recently acquired skills but I got stucked. The problem is this:
First I change the mapping of the APIC through the IA32_APIC_BASE MSR to something like 0x28000, then I read some APIC parameters ( Local APIC ID, Max LVT, APIC Version ) from 0xC0082020 & 0xC0082020 ( I use paging and I have a whole GB from 0xC0000000 to the end ). In Bochs and VMWare works great, but when I really boot into this little application ( I mean like a really OS ) it gets totally frozen. First I thought it could be something wrong with the video, so, I tried to make it triple fault by loading the GDT with a wrong address, using floating point math and making a page fault but it didn't work... I don't know what's going on... I'm going mad !!!
Here is a little of code:
Code: Select all
// Enable APIC
reg_t *pLVT = ( reg_t * ) ( ( reg_t ) pApicBase + 0xf0 );
*pLVT = 0x1ff;
// Error LVT
pLVT = ( reg_t * ) ( ( reg_t ) pApicBase + 0x370 );
*pLVT = 0x100ff;
// Timer LVT
pLVT = ( reg_t * ) ( ( reg_t ) pApicBase + 0x320 );
*pLVT = 0x100ff;
// LINT0 LVT
pLVT = ( reg_t * ) ( ( reg_t ) pApicBase + 0x350 );
*pLVT = 0x100ff;
// LINT1 LVT
pLVT = ( reg_t * ) ( ( reg_t ) pApicBase + 0x360 );
*pLVT = 0x100ff;
// Perf Mon Counters
pLVT = ( reg_t * ) ( ( reg_t ) pApicBase + 0x340 );
*pLVT = 0x100ff;
// Thermal Sensor
pLVT = ( reg_t * ) ( ( reg_t ) pApicBase + 0x330 );
*pLVT = 0x100ff;
reg_t *pPointer;
// Local Apic
pPointer= ( reg_t * ) ( ( reg_t ) pApicBase + 0x20 );
iLocalApic = *( ( int * ) pPointer ) >> 24;
pPointer = ( reg_t * ) ( ( reg_t ) pApicBase + 0x30 );
iVersionApic = *( ( volatile int * ) pPointer );
iMaxLVT = ( iVersionApic >> 16 ) & 0xff;
iVersionApic &= 0xff;
Also, I've found this on the Linux kernel:
Code: Select all
static int modern_apic(void)
{
unsigned int lvr, version;
/* AMD systems use old APIC versions, so check the CPU */
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
boot_cpu_data.x86 >= 0xf)
return 1;
lvr = apic_read(APIC_LVR);
version = GET_APIC_VERSION(lvr);
return version >= 0x14;
}
Thanks so much for reading !!!
And sorry for my English ( specially the verbs... )