Page 1 of 2

Local apic timer initializing

Posted: Wed Apr 07, 2010 5:09 am
by lemonyii
Hi

I have been stuck for too long in this problem
I follow the instructions form
http://forum.osdev.org/posting.php?mode=post&f=1
and set my apic timer,and corrected some place by posting my previous question at
http://forum.osdev.org/viewtopic.php?f= ... =APIC+init
but it still does not work.

the timer has got a decreasing in CCR,and i checked the IF ,surely 1,
but noting happend,never.
i do this in bochs and the CPU emulated is Pentium 4.(i did in vmware too,but noting different).
it is in 64bit mode.so i am doubting if there are some difference in 64bit mode,such TPR,which i set to be always 0, or i got some mistake in initializing.
my code:

Code: Select all

extern i64 APIC_init(){
	sys_call(0ULL,_SYSCALL_LEVEL0,init_apic);
	sys_call(1ULL,_SYSCALL_SET_INT,INT_VECTOR_IRQ0,_int_handler_timer,SYS_INT_HANDLER_TYPE_INT64,0ULL,0ULL);
	sys_call(0ULL,_SYSCALL_LEVEL0,set_apic_timer,0x8000,0xB0,0x00020000|INT_VECTOR_IRQ0);
	return 0;
}

bits 	64
align 	16
init_apic: 				
		pushf					
		cli
		push	rcx
		push	rsi
				
		mov  	rcx,1Bh    		
		rdmsr      				
		and  	rax,0xfffffffffffff000 
		mov  	rsi,rax    		
		mov		eax,0x000001FF	;0x000001FF -> 0xFFE000F0 - enable local APIC  and set spurious int vector to 0xFF
		mov  	[rsi+0xF0],eax   
		mov		eax,0xFFFFFFFF	;0xFFFFFFFF -> 0xFEE000E0 - set destination format register to flat model
		mov		[rsi+0xE0],eax	
		mov		eax,0x00000000	;0x00000000 -> 0xFEE00080 - set the task priority register to accept all interrupts
		mov		[rsi+0x80],eax	
		
		xor		rax,rax
		pop		rsi
		pop		rcx
		popf
		ret

align 	16
set_apic_timer:				;init_apic_timer(CR,DCR,LVT)
		;0x0000000B -> 0xFEE003E0 - set timer to divide by 1
		;0x00020040 -> 0xFEE00320 - enable timer, set periodic mode, set int vector to 0x40
		;0x00000064 -> 0xFEE00380 - set initial count to 100 (and make the timer start counting)
		pushf					
		cli
		push	rcx
		push	rsi
				
		mov  	rcx,1Bh    	
		rdmsr      		
		and  	rax,0xfffffffffffff000 
		mov  	rsi,rax    	
		pop		rax				;DCR
		mov		[rsi+0x3E0],eax
		mov		[rsi+0x320],edx ;LVT	
		mov		[rsi+0x380],edi	;CR
		
		xor		rax,rax
		pop		rcx
		popf
		ret

align 	16
_int_handler_timer:
		push	rcx
		push	rsi
		push	rax
		push	rdi
		
		mov  	rcx,1Bh    		
		rdmsr      				
		and  	rax,0xfffffffffffff000 
		mov  	rsi,rax    	
		;EOI
		xor		rax,rax		
		mov		[rsi+0xB0],eax
		;do something
		mov		rcx,80*200
		mov		rdi,0xb8000
		mov		rax,0x7244
		rep
		stosw

		pop		rdi
		pop		rax
		pop		rsi
		pop		rcx
		iretq
i think i really need some successfully tested code.
help!
thx

Re: Local apic timer initializing

Posted: Wed Apr 07, 2010 8:28 am
by Brendan
Hi,

I love code with good comments, because good comments make bugs stand out.

Code: Select all

%define LAPIC_timer_divisor        0x03E0
%define LAPIC_timer_vector         0x0320
%define LAPIC_timer_initial_count  0x0380


;void init_apic_timer(uint32_t CR, uint32_t DCR, uint32_t LVT)

;Input
; rsi    Local APIC timer divisor (0x0000000B = divide by 1)
; rdx    Local APIC timer LVT (0x00020040 = enable timer, set periodic mode, set int vector to 0x40)
; rdi    Local APIC timer initial count (0x00000064 = 100 ticks)

    align 16

set_apic_timer:            
    pushf                                   ;Save flags      
    cli                                     ;Disable IRQs earlier than necessary
    push rcx                                ;Save RCX
    push rsi                                ;Save Local APIC timer divisor

    mov rcx,1Bh                             ;rcx = model specific Local APIC base MSR
    rdmsr                                   ;edx:eax = model specific Local APIC base MSR (hopefully)
    and rax,0xfffffffffffff000              ;rax = 32-bit physical address of Local APIC (hopefully)
    mov rsi,rax                             ;rsi = 32-bit physical address of Local APIC (hopefully)
    pop rax                                 ;rax = Local APIC timer divisor
    mov [rsi+LAPIC_timer_divisor],eax       ;Set Local APIC timer divisor to value from input parameter that was in rsi
    mov [rsi+LAPIC_timer_vector],edx        ;Set Local APIC vector to the high 32-bits of the Local APIC base MSR
    mov [rsi+LAPIC_timer_initial_count],edi ;Set Local APIC initial count to value from input parameter that was in rdi

    xor rax,rax                             ;rax = zero, because the return value matters for functions that return "void"
    pop rcx                                 ;Restore RCX
    popf                                    ;Restore flags and (potentially) enable IRQs later than necessary
    ret

Cheers,

Brendan

Re: Local apic timer initializing

Posted: Wed Apr 07, 2010 10:31 am
by lemonyii
Hi,
Brendan!
thank you for your replying!
I am so excited when i see your reply!Because i feel your name is so similar,and i am a fish,both here and in OS!
i tried your code,but nothing different.
so i am thinking if i got a mistake somewhere else.would you please remind me?
can the process with a privillige 1 got interrupted? or TPR=0 is making it strange?
my GDT and TSS:
Code:

Code: Select all

align    16,db 0
tmp_gdt:
   .NULL   dd   0
         dd   0
   .D0:   DD   0FFFFH
         DD   0209200H
   .D1:   DD   0FFFFH
         DD   020B200H
   .D2:   DD   0FFFFH
         DD   020D200H
   .D3:   DD   0FFFFH
         DD   020F200H
   .C0:   dd   0FFFFH         
         DD   0AF9A00H      
   .C1:   dd   0FFFFH
         DD   0AFBA00H
   .C2:   dd   0FFFFH
         DD   0AFDA00H
   .C3:   dd   0FFFFH
         DD   0AFFA00H
   .TSS:   dd   0                        ;THIS WOULD BE INITIALIZED AT KERNEL INITIALING
         dd   0
         DD   0         ;base 63-32
         DD   0         ;Reserved

GDTLEN      EQU   $-tmp_gdt   
SegD0      equ tmp_gdt.D0-tmp_gdt
SegD1      equ tmp_gdt.D1-tmp_gdt
SegD2      equ tmp_gdt.D2-tmp_gdt
SegD3      equ tmp_gdt.D3-tmp_gdt
SegC0      equ   tmp_gdt.C0-tmp_gdt
SegC1      equ   tmp_gdt.C1-tmp_gdt
SegC2      equ   tmp_gdt.C2-tmp_gdt
SegC3      equ   tmp_gdt.C3-tmp_gdt
SelectorTSS equ tmp_gdt.TSS-tmp_gdt
GdtPtr:      dw   GDTLEN-1
         DD   0
         DD   0

;== TSS ==========================================      
align    16,db 0
tss:
   .reserved0   dd   0
   .rsp0      dd   0
            dd   0
   .rsp1      dd   0
            dd   0
   .rsp2      dd   0
            dd   0
   .reserved1   dd   0
   .reserved2   dd   0
   .ist1      dd   0
            dd   0
   .ist2      dd   0
            dd   0
   .ist3      dd   0
            dd   0
   .ist4      dd   0
            dd   0
   .ist5      dd   0
            dd   0
   .ist6      dd   0
            dd   0
   .ist7      dd   0
            dd   0
   .reserved3   dd   0
   .reserved4   dd   0
   .reserved5   DW   0
   .IOMapBase   dw   0xffff         ;somewhere invalid
   ;.IOMap      dd   0xffffffff      ;to ensure that it works well
   
TSSLEN      equ   $-tss
idt may not have problems,for i can perform syscalls through interruption for many times.
i really hope you can help me shot this defusing trouble.
thx.

Re: Local apic timer initializing

Posted: Wed Apr 07, 2010 11:08 am
by Brendan
Hi,
lemonyii wrote:i tried your code,but nothing different.
so i am thinking if i got a mistake somewhere else.would you please remind me?
My code is exactly the same as your code, except I added comments. If you read the comments you'll see what the code actually does (and find the bug)...


Cheers,

Brendan

Re: Local apic timer initializing

Posted: Thu Apr 08, 2010 12:22 am
by lemonyii
My code is exactly the same as your code, except I added comments
i found it before i use it.but
If you read the comments you'll see what the code actually does (and find the bug)...
What i have got changed is just

Code: Select all

    mov 	rcx,1Bh                         ;rcx = model specific Local APIC base MSR
    rdmsr                                   ;edx:eax = model specific Local APIC base MSR (hopefully)
	mov		rsi,rdx						;rsi = higher 32bit 
	shl		rsi,32
    and 	rax,0xfffffffffffff000           ;rax = lower 32-bit physical address of Local APIC (hopefully)
    mov 	esi,eax                           ;rsi = 64-bit physical address of Local APIC (hopefully)
still nothing happening though the timer is decreasing.
i'm trying.
thx

Re: Local apic timer initializing

Posted: Thu Apr 08, 2010 10:24 am
by Brendan
Hi,
lemonyii wrote:
If you read the comments you'll see what the code actually does (and find the bug)...
What i have got changed is just[/code]
Did you notice the ";Set Local APIC vector to the high 32-bits of the Local APIC base MSR" comment, or do I need to tattoo your retinas?


Cheers,

Brendan

Re: Local apic timer initializing

Posted: Thu Apr 08, 2010 10:44 pm
by Love4Boobies
Brendan wrote:Did you notice the ";Set Local APIC vector to the high 32-bits of the Local APIC base MSR" comment, or do I need to tattoo your retinas?
High, low, LVT, base MSR, what's the difference? A fish with a tattooed retina sounds far more impressive.

Re: Local apic timer initializing

Posted: Thu Apr 08, 2010 11:34 pm
by lemonyii
Err... :mrgreen:
Brendan wrote: Did you notice the ";Set Local APIC vector to the high 32-bits of the Local APIC base MSR" comment
Brendan
what does it mean? are you suer it is the high 32-bits of THE LAPIC BASE MSR?
i turned the IA32&INTEL64...(2008) again and again but i cannot find such a sentense.
And i changed my code to be like this:

Code: Select all

mov 	rcx,1Bh                         ;rcx = model specific Local APIC base MSR
rdmsr                                   ;edx:eax = model specific Local APIC base MSR (hopefully)
mov		rsi,rdx						;rsi = higher 32bit 
shl		rsi,32
and 	rax,0xfffffffffffff000           ;rax = lower 32-bit physical address of Local APIC (hopefully)
mov 	esi,eax                           ;rsi = 64(in fact 32)-bit physical address of Local APIC (hopefully)
pop 	rax                                 ;rax = Local APIC timer divisor
mov 	[rsi+LAPIC_timer_divisor],eax       ;Set Local APIC timer divisor to value from input parameter that was in rsi
mov 	[rsi+LAPIC_timer_vector],edx        ;Set Local APIC vector to the high 32-bits of the Local APIC base MSR
mov 	[rsi+LAPIC_timer_initial_count],edi ;Set Local APIC initial count to value from input parameter that was in rdi
mov		eax,esi			;eax =  apic base
mov		rcx,0x1B		;apic base MSR
wrmsr					;apic base MSR <- edx:eax
but it get even worse:the CCR will be always 0xffffffffffffffff.
some more help is needed...
thank you so much!

Re: Local apic timer initializing

Posted: Fri Apr 09, 2010 12:35 pm
by Combuster
The bottom line here would be that you need to learn how to program. And that isn't just putting together words like most people seem to think, but know how to find and correct the wrong combinations.

Re: Local apic timer initializing

Posted: Fri Apr 09, 2010 8:32 pm
by lemonyii
well...
at least i solved a problem for another fish with a tattooed retina at
http://forum.osdev.org/viewtopic.php?f=1&t=21812
before i got my only problem solved.
and you with 5 stars here really frightened me! and i have never enjoyed such a feast.
i will keep on my long march on this which has been a month.
thx

Re: Local apic timer initializing

Posted: Fri Apr 09, 2010 8:56 pm
by Love4Boobies
Okay, here's another hint: what are you supposed to write in the LVT timer register?

Re: Local apic timer initializing

Posted: Fri Apr 09, 2010 9:01 pm
by Brendan
Hi,
lemonyii wrote:i will keep on my long march on this which has been a month.
Do you understand that EDX and RDX are the same register?

For example, you can't put 0x12345678 into RDX, then load 0x9ABCDEF into EDX, then expect RDX to still contain 0x12345678?


Cheers,

Brendan

Re: Local apic timer initializing

Posted: Fri Apr 09, 2010 10:16 pm
by lemonyii
PROBLEM SOLVED!!!! :P :lol: =D> [-o<
i rewrite it in C,and then....aha!!!
long march has been end!
and i think edx is the lower 32bits of rdx, and change the edx,the high 32bits of rdx,will remain unchanged,right?
i have write much more in assembly than in C,because i got many problems in complier,
e.g. i spend 3 week to build a cross complie evironment( i tried to used linux,but the driver and LAN problems killed the idea),
and i spend almost a week to learn ELF,and just a problem about alignment and BSS had led to another long march before.
but the fact proved that i am still not good at assemly.
so,i will try to write more in C in the future.
and now i feel it that the most part in solving problems is to find where it to wrong.
And , thank you so much!

Re: Local apic timer initializing

Posted: Fri Apr 09, 2010 10:36 pm
by Love4Boobies
lemonyii wrote:PROBLEM SOLVED!!!! :P :lol: =D> [-o<
i rewrite it in C,and then....aha!!!
long march has been end!
[-X

Code: Select all

; EDX has the right value set for the LVC timer register on input

.
.
.
rdmsr                                      ;Rewrites EDX in the process of dumping the base MSR
.
.
.
mov    [rsi+LAPIC_timer_vector],edx        ;Oops!
.
.
.

Re: Local apic timer initializing

Posted: Fri Apr 09, 2010 11:54 pm
by lemonyii
oh! i got it!
hell the rdmsr !
i should have understand when i was tattooed retina by Brendan :lol:
and the excuse for that is my official language is not English so that i got a misunderstand at that time
thx