SMP table scanning
Posted: Sun Jul 20, 2008 10:44 am
Hello all! Heres my smp code, which scans for the mp floating pointer and the mp config,entries for processors,and similar stuff.
So this code works in finding the _MP_ and the PCMP, i also get to the entries. But i find too many processors even when configuring bochs with a uniprocessor, and i don't find an ioapic which is enabled... Heres the output for Bochs 4 processors:
Booting 'K' [02:39:21 am]
kernel /kernel
[Multiboot-kludge, loadaddr=0x100000, text-and-data=0x1a9b0, bss=0xd70c, ent
ry=0x100000]
Video size:2000 initiated
Init memory allocator
Processor:Pentium 60/66 Family:5 Model:1 Stepping:3
Speed:8 Mhz,MMX FPU:initialized
_MP_,PCMP fd000.proc.proc.proc.proc.proc.proc.ioapic.iointa.linta
Init keyboard:AT
Scheduler initiating
Drive:62730 sectors
OHCI:not found
Error:Invalid parameter(s)
Cannot read disk lba:42973875
Partitions:0)FAT321)NTFS 2)FAT16
ATA hd initiated
Init finished
vm>
The output shows that it found 6 processors, with none of them being appended with a ':boot' according to the code. If the 1st bit is set then it should be a boot processor... Besides the ioapic that is found is not enabled, as i didn't get it when i didn't print the ones not enabled. The procs too are weird with some enabled, some not enabled.
I think theres some trouble in me checking the bootstrap bit. But i think its correct. So what is going on?
Code: Select all
#include <std.h>
#include <memory.h>
#include <type.h>
#include <error.h>
#define MP_SIGL 0x5f504d5f
#define MP_SIGSTR "_MP_"
#define MP_CONFIG_SIGL 0x504d4350
#define MP_CONFIG_SIGSTR "PCMP"
struct mp {
u8 sig[4];
u32 config_ptr;
u8 len;
u8 ver;
u8 checksum;
u8 f1;
u8 f2;
u8 fr[3];
}__attribute__((packed))*mp;
struct mp_config {
u8 sig[4];
u16 len;
u8 ver;
u8 checksum;
u8 oem_id[8];
u8 prod_id[12];
u32 oem_ptr; /*For an optional oem table*/
u16 oem_sz;
u16 nr_entries;
u32 lapic_addr;
u16 ext_len;
u8 ext_checksum;
}__attribute__((packed))*mp_config;
#define ENT_PROC 0
#define ENT_BUS 1
#define ENT_IOAPIC 2
#define ENT_IOINTA 3 /*IO interrupt assignment*/
#define ENT_LINTA 4 /*Local interrupt assignment*/
/*A processor entry*/
struct mp_proc {
u8 type;
u8 lapic_id;
u8 lapic_ver;
u8 flags; /*bit0:enabled proc, bit1:bootstrap*/
u32 sig;
u32 feat;
u8 resvd[8];
}__attribute__((packed));
/*ioapic entry*/
struct mp_ioapic {
u8 type;
u8 id;
u8 ver;
u8 flags; /*bit0: enabled ioapic*/
u32 addr;
}__attribute__((packed));
#define MP_PROC_SZ 20
#define MP_IOAPIC_SZ 8
#define MP_BUS_SZ 8
#define MP_IOINTA_SZ 8
#define MP_LINTA_SZ 8
struct processor {
struct mp_proc *proc; /*Note:This points to actual entry by BIOS. We have not made a local copy*/
struct processor *next;
}*processors=NULL;
struct ioapic {
struct mp_ioapic *ioapic;
struct ioapic *next;
}*ioapics=NULL;
/*This is just a local linked list, nothing to do with the bios tables*/
/*Add a processor to the linked list*/
int add_processor(struct mp_proc *x)
{
struct processor *tail;
if(!((x->flags) & 1)) {/*Disabled*/
return NULL;
}
if(x->flags & 2) /*Bootstrap*/
printk(":boot");
if(!processors) {
processors=new(struct processor);
processors->next=NULL;
tail=processors;
} else {
for(tail=processors;tail->next;tail=tail->next);
tail->next=new(struct processor);
tail=tail->next;
tail->next=NULL;
}
tail->proc=x;
return NULL;
}
/*Add an ioapic to the linked list*/
int add_ioapic(struct mp_ioapic *x)
{
struct ioapic *tail;
if(!ioapics) {
ioapics=new(struct ioapic);
ioapics->next=NULL;
tail=ioapics;
} else {
for(tail=ioapics;tail->next;tail=tail->next);
tail->next=new(struct ioapic);
tail=tail->next;
tail->next=NULL;
}
tail->ioapic=x;
return NULL;
}
/*Build list by scanning the entries after the config table*/
int build_list()
{
int i;
u8 *ent;
struct mp_proc *proc;
struct mp_ioapic *ioapic;
mp_config=(struct mp_config *)mp->config_ptr;
if((*((u32 *)mp_config->sig))!=MP_CONFIG_SIGL)
return ELLERR;
printk("PCMP %x",mp_config); /*found a PCMP*/
ent=(char *)((u32)mp_config+sizeof(struct mp_config)); /*Go to the array of entries*/
for(i=0;i<mp_config->nr_entries;i++) {
switch(ent[0]) { /*Read the type*/
case ENT_PROC:
printk(".proc");
add_processor((struct mp_proc *)ent);
ent+=MP_PROC_SZ;
break;
case ENT_BUS:
printk(".bus");
ent+=MP_BUS_SZ;
break;
case ENT_IOAPIC:
printk(".ioapic");
add_ioapic((struct mp_ioapic *)ent);
ent+=MP_IOAPIC_SZ;
break;
case ENT_IOINTA:
printk(".iointa");
ent+=MP_IOINTA_SZ;
break;
case ENT_LINTA:
printk(".linta");
ent+=MP_LINTA_SZ;
break;
default:
goto inv_exit;
}
}
inv_exit:
return NULL;
}
int compute_checksum(char *b,int sz)
{
int i;
unsigned char c=0;
for(i=0;i<sz;i++) {
c+=b[i];
}
return (int)c;
}
#define EBDA_START 0x40E
#define EBDA_SEARCH_SZ 0x400
#define BASE_START 0xa0000
#define BASE_SEARCH_SZ 0x400
#define ROM_START 0xf0000
#define ROM_END 0x100000
/*Search for the mp floating pointer in the above 3 areas*/
int search_mp()
{
u32 *i=NULL;
int c;
for(i=0;(u32)i<0x400;i++) { /*RAM start 1k*/
if(*i==MP_SIGL) {
mp=(struct mp *)i;
return NULL;
}
}
for(i=EBDA_START;(u32)i<EBDA_START+EBDA_SEARCH_SZ;i++) {
if(*i==MP_SIGL) {
mp=(struct mp *)i;
return NULL;
}
}
for(i=BASE_START;(u32)i<BASE_START+BASE_SEARCH_SZ;i++) {
if(*i==MP_SIGL) {
mp=(struct mp *)i;
return NULL;
}
}
for(i=ROM_START;(u32)i<ROM_END;i++) {
if(*i==MP_SIGL) {
mp=(struct mp *)i;
return NULL;
}
}
return ENODEV;
}
int init_smp()
{
if(!search_mp()) {
printk("\n_MP_,");
build_list(); /*Build a linked list of procs and ioapics*/
return NULL;
}
}
Booting 'K' [02:39:21 am]
kernel /kernel
[Multiboot-kludge, loadaddr=0x100000, text-and-data=0x1a9b0, bss=0xd70c, ent
ry=0x100000]
Video size:2000 initiated
Init memory allocator
Processor:Pentium 60/66 Family:5 Model:1 Stepping:3
Speed:8 Mhz,MMX FPU:initialized
_MP_,PCMP fd000.proc.proc.proc.proc.proc.proc.ioapic.iointa.linta
Init keyboard:AT
Scheduler initiating
Drive:62730 sectors
OHCI:not found
Error:Invalid parameter(s)
Cannot read disk lba:42973875
Partitions:0)FAT321)NTFS 2)FAT16
ATA hd initiated
Init finished
vm>
The output shows that it found 6 processors, with none of them being appended with a ':boot' according to the code. If the 1st bit is set then it should be a boot processor... Besides the ioapic that is found is not enabled, as i didn't get it when i didn't print the ones not enabled. The procs too are weird with some enabled, some not enabled.
I think theres some trouble in me checking the bootstrap bit. But i think its correct. So what is going on?