summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel <m.i@gmx.at>2018-09-09 00:26:30 +0200
committerMiguel <m.i@gmx.at>2018-09-09 00:26:30 +0200
commit9dabe01545644dd78448d8d489616872f14d964b (patch)
tree83a939a54ffa27f575dbdf930140b8353f54365c
parent9fde748acea83d775e367a64858414b674f05b13 (diff)
lapic bus speed probing and starting switch to ioapic
-rw-r--r--README.md2
-rw-r--r--asm/asm_pic.asm6
-rw-r--r--asm/asm_pit.s22
-rw-r--r--kernel/gdt.c5
-rw-r--r--kernel/interrupts.c2
-rw-r--r--kernel/kernel.c44
-rw-r--r--kernel/smp.c58
7 files changed, 88 insertions, 51 deletions
diff --git a/README.md b/README.md
index efd3a29..207957c 100644
--- a/README.md
+++ b/README.md
@@ -98,6 +98,8 @@ Discontinued Features
Todos
-----
+* ipxe (network drivers?)
+* io_wait?
* cpuid (i686) check apic?
* lapic / spurious . ioapic
* newlib reentrant struct!!
diff --git a/asm/asm_pic.asm b/asm/asm_pic.asm
index 2514be7..8a90fdf 100644
--- a/asm/asm_pic.asm
+++ b/asm/asm_pic.asm
@@ -78,6 +78,12 @@ in al, 0xA1 ; read in the primary PIC Interrupt Mask Register (IMR)
and al, 0x00 ; 0xEF => 11101111b. This sets the IRQ4 bit (Bit 5) in AL
out 0xA1, al ; write the value back into IMR
+;disable
+
+;mov al, 0xff
+;out 0xa1, al
+;out 0x21, al
+
ret
;;;;;;;;;;;;;;;;;;;;
diff --git a/asm/asm_pit.s b/asm/asm_pit.s
index 8be29cb..28fd784 100644
--- a/asm/asm_pit.s
+++ b/asm/asm_pit.s
@@ -49,7 +49,7 @@ asm_pit_tick:
.macro asm_pit_sleep val
- mov $0x00110000, %al // chan 0 / mode 0
+ mov $0b00110000, %al // chan 0 / mode 0
outb %al,$0x43
// LSB first
@@ -57,18 +57,20 @@ asm_pit_tick:
out %al, $0x40
xchg %ah,%al
out %al, $0x40
-
- // check if finished
- mov $0xE2, %al
- outb %al,$0x43
//sleep until finished
- //7th bit determines if finished
+ //7th bit (0-7) determines if finished
sleep\val:
- inb $0x40, %al
- or $0b1000000, %al
- cmp $0b1000000, %al
- jne sleep\val
+
+ // read back command
+ mov $0b11100010, %al
+ outb %al,$0x43
+
+ inb $0x40, %al
+ and $0b10000000, %al
+
+ cmp $0b10000000, %al
+ jne sleep\val
ret
diff --git a/kernel/gdt.c b/kernel/gdt.c
index 0657387..bf8f203 100644
--- a/kernel/gdt.c
+++ b/kernel/gdt.c
@@ -7,7 +7,8 @@
#define GDT_SIZE 6
//https://wiki.osdev.org/Task_State_Segment
-tss_struct sys_tss[SMP_MAX_PROC]; //Define the TSS as a global structure
+//Define the TSS as a global structure, boah TODO: move to own page?
+tss_struct sys_tss[SMP_MAX_PROC];
void install_tss(uint32_t cpu,uint32_t esp0){
@@ -19,6 +20,7 @@ void install_tss(uint32_t cpu,uint32_t esp0){
// now set the IO bitmap (not necessary, so set above limit)
// sys_tss.iomap = ( unsigned short ) sizeof( tss_struct );
}
+
typedef struct GDT_struct
{
uint32_t base;
@@ -150,6 +152,7 @@ void gdt_init()
setup_gdt(gdt_struct);
}
+
void setup_gdt(uint8_t *gdt_struct)
{
asm_setup_gdt(&gdt_struct[0],8*GDT_SIZE);
diff --git a/kernel/interrupts.c b/kernel/interrupts.c
index acf781d..30d8994 100644
--- a/kernel/interrupts.c
+++ b/kernel/interrupts.c
@@ -59,7 +59,7 @@ uint32_t interrupt_handler(uint32_t esp, uint32_t irq)
{
// DO NOT WRITE INSIDE INTERRUPTS!! COZ IT ACQUIRES LOCK AND WE WILL DEADLOCK
-// klog("int: %d on 0x%x",irq,apicID());
+ //klog("int: %d on 0x%x",irq,apicID());
if(irq==0)asm_pit_tick();
// mouse and kb
diff --git a/kernel/kernel.c b/kernel/kernel.c
index 17bf9b7..e20d2e1 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -25,12 +25,13 @@ void kernel_main(uint32_t eax,uint32_t ebx)
serial_init();
klog("FOOL-OS ver-%s (%s)",GIT_REVISION,__DATE__);
- // while(1);
+ klog("Global Descriptor Table (GDT) init ...");
+ gdt_init();
klog("Interrupt Vector Table (IVT) init ...");
interrupts_init(0x08);
- klog("Setting up PIC");
+ klog("Remapping & (not yet Disabling) PIC ...");
asm_pic_setup();
klog("Keyboard init ...");
@@ -39,24 +40,27 @@ void kernel_main(uint32_t eax,uint32_t ebx)
klog("Mouse init ...");
mouse_init();
- klog("Global Descriptor Table (GDT) init ...");
- gdt_init();
-
- klog("Multiboot Structures init ... ");
+ // gather some info (before we start paging)
+ klog("Search / Read Multiboot Structures ... ");
multiboot_information *info;
info=get_multiboot(eax, ebx);
+ klog("Search / Read ACPI Structures... ");
+ smp_processors procdata;
+ bool acpi_found=acpi_find(&procdata);
+
+ klog("Search / Read MP Structures... ");
+ smp_processors procdata2;
+ bool mp_found=mp_find(&procdata2);
+ //
+
+ // memory management
klog("Memory init ... ");
uint32_t kernel_blocks=mem_init(info);
- klog("Symmetrical Multi Processing (SMP) init ... ");
- smp_processors procdata;
- if(!acpi_find(&procdata))
- if(!mp_find(&procdata))kpanic("No ACPI and no MP found!");
-
- // searching for ACPI etc.. in physical mem has to be performed before that.
klog("Vritual Memory / Paging init ... ");
pdirectory *dir=vmem_init(kernel_blocks,(uint32_t)info->framebuffer_addr,procdata.local_apic_address);
+ //
klog("Ram Filesystem init ... ");
fs_mount(info);
@@ -81,16 +85,12 @@ void kernel_main(uint32_t eax,uint32_t ebx)
uint64_t unixtime=timer_init();
klog("Unix Time = %u seconds)",unixtime);
- klog("Setting Interrupt Flag on BSP ...");
+ klog("Enable Interrupts & Unlock application processors ... ");
asm_smp_unlock();
- x86_sti(); // this will start processing hardware interrupts.
-
- // TODO : pray that this is reached BEFORE scheduler kicks in!?
-
- klog("Unlock application processors ... ");
+ // TODO : bsp sti needs to happen before ap sti? seriously? why? is this guaranteed now?
+ // TODO: switch to ioapic
+ x86_sti(); // this will start processing hardware interrupts
- while(1){ // now just wait until our scheduler kicks in.
-// klog("bsp");
- asm("hlt");
- }
+ // now just wait until our scheduler kicks in.
+ while(1)asm("hlt");
}
diff --git a/kernel/smp.c b/kernel/smp.c
index da91148..b2ce6b0 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -43,6 +43,7 @@ volatile uint8_t proc;
uint32_t cpu_counter[SMP_MAX_PROC];
uint32_t local_apic_addr;
+uint32_t countdown;
void writeAPIC(uint32_t offset, uint32_t value)
{
@@ -81,6 +82,35 @@ void apicEnable()
}
+/** select mode : divisor.
+ * 0 - 1
+ * 1 - 2
+ * 2 - 4
+ * 3 - 8
+ * 4 - 16
+ * 5 - 32
+ * 6 - 64
+ * 7 - 128
+ */
+
+uint32_t probeBusSpeed(uint32_t sel)
+{
+ uint32_t div[]={1,2,4,8,16,32,64,128};
+ uint32_t reg[]={0b1011,0,1,2,3,0b1000,0b1001,0b1010};
+
+ uint32_t divisor=div[sel];
+
+ klog("Probing bus speed for 50ms (div=%d)) ...",divisor);
+ writeAPIC(APIC_TMRDIV, reg[sel]);
+ writeAPIC(APIC_TMRINITCNT, 0xFFFFFFFF);
+// for(int i=0;i<20;i++)
+ asm_pit_sleep_50ms();
+ //writeAPIC(APIC_LVT_TMR, APIC_LVT_INT_MASKED); //??
+ uint32_t ticksInS = 0xFFFFFFFF - readAPIC(APIC_TMRCURRCNT);
+ ticksInS*=20; // adjust to one full second.
+ klog("%d MHz (%d Hz) bus speed (ticks=%d)",ticksInS/(1000000/divisor),ticksInS*divisor,ticksInS/20);
+ return ticksInS*divisor;
+}
void smp_main()
{
// setup stack
@@ -99,7 +129,6 @@ void kernel_ap()
int_install();
gdt_init();
- uint32_t countdown=0x0fffffff; // TODO: calc to be constant, depending on bus speed. (use pit for measurement?)
writeAPIC(APIC_TMRDIV, 0x3);
writeAPIC(APIC_LVT_TMR, 200 | TMR_PERIODIC);
writeAPIC(APIC_TMRINITCNT, countdown);
@@ -151,9 +180,18 @@ void smp_start_aps(smp_processors *pros)
{
// TODO: check if local APIC is present via CPUID (P6 (i686) and above)
local_apic_addr=pros->local_apic_address;
-
klog("bsp local apic id: 0x%08X",apicID());
+ apicEnable(); // bsp apic seems to be enabled anyway.
+
+ uint32_t speed=probeBusSpeed(4); // get bus speed (divisor: 16)
+
+ // setup apic timer
+ countdown=speed/16; // tick once a second
+ writeAPIC(APIC_TMRDIV, 0x3); // divisor 16
+ writeAPIC(APIC_LVT_TMR, 200 | TMR_PERIODIC); // on interrupt 200
+ writeAPIC(APIC_TMRINITCNT, countdown);
+
for(int i=0;i<pros->processors;i++)
{
if(pros->boot==i)continue;
@@ -177,19 +215,5 @@ void smp_start_aps(smp_processors *pros)
// TODO retry 110 SIPI with 1s timeout
}
-
- apicEnable(); // bsp seems to be enabled anyway.
-
- writeAPIC(APIC_TMRDIV, 0x3);
- writeAPIC(APIC_TMRINITCNT, 0xFFFFFFFF);
- //asm_pit_sleep_1ms();
- //writeAPIC(APIC_LVT_TMR, APIC_LVT_INT_MASKED); //??
- uint32_t ticksInS = 0xFFFFFFFF - readAPIC(APIC_TMRCURRCNT);
-
- klog("%d MHz bus speed",ticksInS/1000);
-
- uint32_t countdown=0x0fffffff; // TODO: calc to be constant, depending on bus speed. (use pit for measurement?)
- writeAPIC(APIC_TMRDIV, 0x3);
- writeAPIC(APIC_LVT_TMR, 200 | TMR_PERIODIC);
- writeAPIC(APIC_TMRINITCNT, countdown);
}
+