Advice needed immediately
Re:Advice needed immediately
Hi people, can anybody explain the problem with following code?
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Load Task register.
mov ax, SYSTEM_TSS
ltr ax
; Initialize thread tss entries.
lea eax, [thread1_code] ; thread1 entry point
mov dword [thread1_eip],eax
mov dword [thread1_esp],esp
lea eax, [thread2_code] ; thread2 entry point
mov dword [thread2_eip],eax
mov dword [thread2_esp],esp
;call thread task
jmp THREAD1_TSS:0
jmp $ ;HALT!!!
thread1_code:
mov esi, thread1_msg
call PRINTMSG32
;jmp $
jmp SYSTEM_TSS
thread2_code:
mov esi, thread2_msg
call PRINTMSG32
jmp $
This code should write thread1_msg onto screen and then swtich back to system_tss. It does write message onto screen but does not successfully swtich back to system_tss. In bochs it gives an error like:
...
00000506315e[HD ] device set to 1 which does not exist
00000713779p[CPU ] >>PANIC<< prefetch: running in bogus memory
00000713779i[SYS ] Last time is 1044879375
00000713779i[CPU ] protected mode
00000713779i[CPU ] CS.d_b = 32 bit
00000713779i[CPU ] SS.d_b = 32 bit
00000713779i[CPU ] | EAX=00000000 EBX=00000000 ECX=00000000 EDX=00000000
00000713779i[CPU ] | ESP=0000fffb EBP=00000000 ESI=000039c5 EDI=00000000
00000713779i[CPU ] | IOPL=0 NV UP EI NG NZ NA PE NC
00000713779i[CPU ] | SEG selector base limit G D
00000713779i[CPU ] | SEG sltr(index|ti|rpl) base limit G D
00000713779i[CPU ] | DS:0010( 0002| 0| 0) 00001000 000fffff 1 1
00000713779i[CPU ] | ES:0010( 0002| 0| 0) 00001000 000fffff 1 1
00000713779i[CPU ] | FS:0010( 0002| 0| 0) 00001000 000fffff 1 1
00000713779i[CPU ] | GS:0010( 0002| 0| 0) 00001000 000fffff 1 1
00000713779i[CPU ] | SS:0010( 0002| 0| 0) 00001000 000fffff 1 1
00000713779i[CPU ] | CS:0018( 0003| 0| 0) 00001000 000fffff 1 1
00000713779i[CPU ] | EIP=3a23a23f (3a23a23f)
00000713779i[CPU ] | CR0=0x60000019 CR1=0x00000000 CR2=0x00000000
00000713779i[CPU ] | CR3=0x00000000 CR4=0x00000000
00000713779i[ ] restoring default signal behavior
00000713779i[CTRL ] quit_sim called with exit code 1
Any advice is welcome. Thanx...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Load Task register.
mov ax, SYSTEM_TSS
ltr ax
; Initialize thread tss entries.
lea eax, [thread1_code] ; thread1 entry point
mov dword [thread1_eip],eax
mov dword [thread1_esp],esp
lea eax, [thread2_code] ; thread2 entry point
mov dword [thread2_eip],eax
mov dword [thread2_esp],esp
;call thread task
jmp THREAD1_TSS:0
jmp $ ;HALT!!!
thread1_code:
mov esi, thread1_msg
call PRINTMSG32
;jmp $
jmp SYSTEM_TSS
thread2_code:
mov esi, thread2_msg
call PRINTMSG32
jmp $
This code should write thread1_msg onto screen and then swtich back to system_tss. It does write message onto screen but does not successfully swtich back to system_tss. In bochs it gives an error like:
...
00000506315e[HD ] device set to 1 which does not exist
00000713779p[CPU ] >>PANIC<< prefetch: running in bogus memory
00000713779i[SYS ] Last time is 1044879375
00000713779i[CPU ] protected mode
00000713779i[CPU ] CS.d_b = 32 bit
00000713779i[CPU ] SS.d_b = 32 bit
00000713779i[CPU ] | EAX=00000000 EBX=00000000 ECX=00000000 EDX=00000000
00000713779i[CPU ] | ESP=0000fffb EBP=00000000 ESI=000039c5 EDI=00000000
00000713779i[CPU ] | IOPL=0 NV UP EI NG NZ NA PE NC
00000713779i[CPU ] | SEG selector base limit G D
00000713779i[CPU ] | SEG sltr(index|ti|rpl) base limit G D
00000713779i[CPU ] | DS:0010( 0002| 0| 0) 00001000 000fffff 1 1
00000713779i[CPU ] | ES:0010( 0002| 0| 0) 00001000 000fffff 1 1
00000713779i[CPU ] | FS:0010( 0002| 0| 0) 00001000 000fffff 1 1
00000713779i[CPU ] | GS:0010( 0002| 0| 0) 00001000 000fffff 1 1
00000713779i[CPU ] | SS:0010( 0002| 0| 0) 00001000 000fffff 1 1
00000713779i[CPU ] | CS:0018( 0003| 0| 0) 00001000 000fffff 1 1
00000713779i[CPU ] | EIP=3a23a23f (3a23a23f)
00000713779i[CPU ] | CR0=0x60000019 CR1=0x00000000 CR2=0x00000000
00000713779i[CPU ] | CR3=0x00000000 CR4=0x00000000
00000713779i[ ] restoring default signal behavior
00000713779i[CTRL ] quit_sim called with exit code 1
Any advice is welcome. Thanx...
Re:Advice needed immediately
I forgot to send tss's and desciptors. Code is running in pmode and no paging.
system_tss:
dw 0, 0 ; back link
dd 0 ; ESP0
dw 0, 0 ; SS0, reserved
dd 0 ; ESP1
dw 0, 0 ; SS1, reserved
dd 0 ; ESP2
dw 0, 0 ; SS2, reserved
dd 0, 0, 0 ; CR3, EIP, EFLAGS
dd 0, 0, 0, 0 ; EAX, ECX, EDX, EBX
dd 0, 0, 0, 0 ; ESP, EBP, ESI, EDI
dw 0, 0 ; ES, reserved
dw 0, 0 ; CS, reserved
dw 0, 0 ; SS, reserved
dw 0, 0 ; DS, reserved
dw 0, 0 ; FS, reserved
dw 0, 0 ; GS, reserved
dw 0, 0 ; LDT, reserved
dw 0, 0 ; debug, IO perm. bitmap
thread1_tss:
dw 0, 0 ; back link
dd 0 ; ESP0
dw 0, 0 ; SS0, reserved
dd 0 ; ESP1
dw 0, 0 ; SS1, reserved
dd 0 ; ESP2
dw 0, 0 ; SS2, reserved
thread1_cr3:
dd 0 ; CR3
thread1_eip:
dd 0, 0x200 ; EIP, EFLAGS (EFLAGS=0x200 for ints)
dd 0, 0, 0, 0 ; EAX, ECX, EDX, EBX
thread1_esp:
dd 0xffff, 0, 0, 0 ; ESP, EBP, ESI, EDI
dw SYS_DATA_SEL, 0 ; ES, reserved
dw SYS_CODE_SEL, 0 ; CS, reserved
dw SYS_DATA_SEL, 0 ; SS, reserved
dw SYS_DATA_SEL, 0 ; DS, reserved
dw SYS_DATA_SEL, 0 ; FS, reserved
dw SYS_DATA_SEL, 0 ; GS, reserved
dw 0, 0 ; LDT, reserved
dw 0, 0 ; debug, IO perm. bitmap
thread2_tss:
dw 0, 0 ; back link
dd 0 ; ESP0
dw 0, 0 ; SS0, reserved
dd 0 ; ESP1
dw 0, 0 ; SS1, reserved
dd 0 ; ESP2
dw 0, 0 ; SS2, reserved
thread2_cr3:
dd 0 ; CR3
thread2_eip:
dd 0, 0x200 ; EIP, EFLAGS (EFLAGS=0x200 for ints)
dd 0, 0, 0, 0 ; EAX, ECX, EDX, EBX
thread2_esp:
dd 0xffff, 0, 0, 0 ; ESP, EBP, ESI, EDI
dw SYS_DATA_SEL, 0 ; ES, reserved
dw SYS_CODE_SEL, 0 ; CS, reserved
dw SYS_DATA_SEL, 0 ; SS, reserved
dw SYS_DATA_SEL, 0 ; DS, reserved
dw SYS_DATA_SEL, 0 ; FS, reserved
dw SYS_DATA_SEL, 0 ; GS, reserved
dw 0, 0 ; LDT, reserved
dw 0, 0 ; debug, IO perm. bitmap
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
and descriptors:
SYSTEM_TSS equ $-gdt
system_tss_desc: dw 103
dw 0 ; set to System TSS.
db 0
db 0x89 ; present, ring 0, 32-bit available TSS
db 0
db 0
THREAD1_TSS equ $-gdt
thread1_tss_desc: dw 103
dw 0
db 0
db 0x89 ; present, ring 0, 32-bit available TSS
db 0
db 0
THREAD2_TSS equ $-gdt
thread2_tss_desc: dw 103
dw 0
db 0
db 0x89 ; present, ring 0, 32-bit available TSS
db 0
db 0
system_tss:
dw 0, 0 ; back link
dd 0 ; ESP0
dw 0, 0 ; SS0, reserved
dd 0 ; ESP1
dw 0, 0 ; SS1, reserved
dd 0 ; ESP2
dw 0, 0 ; SS2, reserved
dd 0, 0, 0 ; CR3, EIP, EFLAGS
dd 0, 0, 0, 0 ; EAX, ECX, EDX, EBX
dd 0, 0, 0, 0 ; ESP, EBP, ESI, EDI
dw 0, 0 ; ES, reserved
dw 0, 0 ; CS, reserved
dw 0, 0 ; SS, reserved
dw 0, 0 ; DS, reserved
dw 0, 0 ; FS, reserved
dw 0, 0 ; GS, reserved
dw 0, 0 ; LDT, reserved
dw 0, 0 ; debug, IO perm. bitmap
thread1_tss:
dw 0, 0 ; back link
dd 0 ; ESP0
dw 0, 0 ; SS0, reserved
dd 0 ; ESP1
dw 0, 0 ; SS1, reserved
dd 0 ; ESP2
dw 0, 0 ; SS2, reserved
thread1_cr3:
dd 0 ; CR3
thread1_eip:
dd 0, 0x200 ; EIP, EFLAGS (EFLAGS=0x200 for ints)
dd 0, 0, 0, 0 ; EAX, ECX, EDX, EBX
thread1_esp:
dd 0xffff, 0, 0, 0 ; ESP, EBP, ESI, EDI
dw SYS_DATA_SEL, 0 ; ES, reserved
dw SYS_CODE_SEL, 0 ; CS, reserved
dw SYS_DATA_SEL, 0 ; SS, reserved
dw SYS_DATA_SEL, 0 ; DS, reserved
dw SYS_DATA_SEL, 0 ; FS, reserved
dw SYS_DATA_SEL, 0 ; GS, reserved
dw 0, 0 ; LDT, reserved
dw 0, 0 ; debug, IO perm. bitmap
thread2_tss:
dw 0, 0 ; back link
dd 0 ; ESP0
dw 0, 0 ; SS0, reserved
dd 0 ; ESP1
dw 0, 0 ; SS1, reserved
dd 0 ; ESP2
dw 0, 0 ; SS2, reserved
thread2_cr3:
dd 0 ; CR3
thread2_eip:
dd 0, 0x200 ; EIP, EFLAGS (EFLAGS=0x200 for ints)
dd 0, 0, 0, 0 ; EAX, ECX, EDX, EBX
thread2_esp:
dd 0xffff, 0, 0, 0 ; ESP, EBP, ESI, EDI
dw SYS_DATA_SEL, 0 ; ES, reserved
dw SYS_CODE_SEL, 0 ; CS, reserved
dw SYS_DATA_SEL, 0 ; SS, reserved
dw SYS_DATA_SEL, 0 ; DS, reserved
dw SYS_DATA_SEL, 0 ; FS, reserved
dw SYS_DATA_SEL, 0 ; GS, reserved
dw 0, 0 ; LDT, reserved
dw 0, 0 ; debug, IO perm. bitmap
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
and descriptors:
SYSTEM_TSS equ $-gdt
system_tss_desc: dw 103
dw 0 ; set to System TSS.
db 0
db 0x89 ; present, ring 0, 32-bit available TSS
db 0
db 0
THREAD1_TSS equ $-gdt
thread1_tss_desc: dw 103
dw 0
db 0
db 0x89 ; present, ring 0, 32-bit available TSS
db 0
db 0
THREAD2_TSS equ $-gdt
thread2_tss_desc: dw 103
dw 0
db 0
db 0x89 ; present, ring 0, 32-bit available TSS
db 0
db 0
Re:Advice needed immediately
Since there are no responses to my very long questions, today I realized that in fact I can switch back to system_tss by call-iret way. However, I still dont know why JMPing from switched task gives an error. I also realized that in fact I never needed to get control back to calling task like the way I did in that code. I mean since all swtiching is done by scheduler, application does not itself even know about if it will be preemted or not. (right?) Anyway... I need to go on... Any ideas are still very very appreciated. Thanx...
Re:Advice needed immediately
Hey cmon gurus how come could you not see my very very stupid mistake overthere? I am the very most stupid of all, I cannot believe it look at here:
Is there a possibility that jmp SYSTEM_TSS will work? It should be jmp SYSTEM_TSS:0. Anyway, I am sorry for taking up that much space, I still cannot believe that I made such a mistake...
Code: Select all
thread1_code:
mov esi, thread1_msg
call PRINTMSG32
;jmp $
jmp SYSTEM_TSS
thread2_code:
mov esi, thread2_msg
call PRINTMSG32
Re:Advice needed immediately
Heh, don't feal too bad, I can't count the number of times I've done stuff like that and thought there was a bug a my code.I am the very most stupid of all, I cannot believe it look at here:
It should.Is there a possibility that jmp SYSTEM_TSS will work?
You might want to look into 'software taskswitching' which is what Curufir was describing. It's much faster than TSS taskswitching, and IMHO, easier. There's some "framework" code for it here:
http://osdev.neopages.net/tutorials/soft_ts.php
K.J.
Re:Advice needed immediately
Well, when I changed this expression into jmp SYSTEM_TSS:0 code started working. When I use jmp SYSTEM_TSS it jumps to a very strange place and causes page fault, and then eventually triple faults. BTW I have no reason for using hardware task switching, I think it is more suitable for standards, I mean hardware stuff. Anyway...
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Advice needed immediately
for the assembler, jmp TSS_SELECTOR is just jmp (near) constant, so you'll jump to the 0x20 th byte, or 0x38, or whatever your selector is ...
Of course it's very unlikely to work.
Of course it's very unlikely to work.
Re:Advice needed immediately
Pype Clicker I hope you read this. I am quite confused on your explanation on scheduler calling time in "Task switch at interrupt" thread. I thought switching task was the only way to handle irq0 so that a task that will be preempted does not need to know about the time it will be switched. OK, to be more simpler: When we use a trap gate for handling irq0 then when a timer interrupt occurs the handler is called in context of current task. Which also means that we have to call scheduler in thje context of current task. However if scheduler decides that this task should be preempted, its state will be saved in the middle of handling a timer interrupt. Right? (Or is it?) So later when we try to switch back to this task then will it go on appropriately? But if we do a task switch on interrupt then at irq0 current task will be saved exactly where it will be running later when it again gets control. Any corrections? Thanx...
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Advice needed immediately
So basically, you would like to have IRQ0 calling task X (the scheduler) which will decide to switch to task B instead of task A ?
This implies too much switches for my tastes, but if you really want to do so, probably the best way is to change the current TSS's "back link" from TSS_A to TSS_B before your task X performs the IRET ...
trying to do a JMP TSS_B:0 in the IRQ0 handler (called by task gate to X) will change the EIP address and the register values of the TSS_X, while the IRET leave that state unmodified (so that the next interrupt also finds a clean state)
This implies too much switches for my tastes, but if you really want to do so, probably the best way is to change the current TSS's "back link" from TSS_A to TSS_B before your task X performs the IRET ...
trying to do a JMP TSS_B:0 in the IRQ0 handler (called by task gate to X) will change the EIP address and the register values of the TSS_X, while the IRET leave that state unmodified (so that the next interrupt also finds a clean state)
Re:Advice needed immediately
OK, this might be a very much specific quesition but I could not find it in the books. How is a new task's eflag initialized?
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Advice needed immediately
You should at least always have the "sticky bit" set (i think it should be BIT1 or something alike) : that bit is constantly set by the hardware, so you should set it as well, imho
For the other bits ... it just depends on what you wish. You can let all the "ALU" flags cleared, but i suppose your question is more about NT, IOPL and IF flags, right ?
I think the best policy is to set them accordingly to what would be their normal state if the program was simply called from another function rather than being started as a new task.
For instance, if your task starts somewhere in user code, just leave the IF bit set, while if you're starting from then end of an interrupt handler, you'll better clear it.
For the other bits ... it just depends on what you wish. You can let all the "ALU" flags cleared, but i suppose your question is more about NT, IOPL and IF flags, right ?
I think the best policy is to set them accordingly to what would be their normal state if the program was simply called from another function rather than being started as a new task.
For instance, if your task starts somewhere in user code, just leave the IF bit set, while if you're starting from then end of an interrupt handler, you'll better clear it.
Re:Advice needed immediately
Hi, firstly thanx... ;D Would doing task switch in the way you(Pype Clicker) told in previous second thread cause any problems?(Other than doing many task switches on every irq0) I know that this is a very general question but I just wanted to take your ideas. I cannot think of any other way of calling scheduler without disturbing currently executing task. I am a little confused on how to implement it, I think a lot of people are doing software task switching which is much simpler, faster and easier. But I want to leave it for some time. Anyway, thanx in advance for any advice.
- Pype.Clicker
- Member
- Posts: 5964
- Joined: Wed Oct 18, 2006 2:31 am
- Location: In a galaxy, far, far away
- Contact:
Re:Advice needed immediately
what i don't understand is why you want so hard to avoid IRQ0 to interrupt the user process ... That's what interrupts are designed for : interrupting a user process and then restore its state transparently to the underlying application ... So if you do the switch within a trap-based (handled within the current task) interrupt handler, it just appears to the application as if the IRQ it didn't see just took more time. period.
Re:Advice needed immediately
John Fines pages? May I ask where I find them?beyond infinity wrote: If you use hardware taskswitching, you might have multiple tss-selectors or just one (this is tricky - see john fines pages for how to do that), which you jump to at every task switch.
Re:Advice needed immediately
John Fine's page:
http://my.execpc.com/CE/AC/geezer/johnfine/index.htm
I want to avoid irq0 interrupt user process becuase firstly I do not know why I want it that way ??? I mean, I just think that interrupts should be handled bylow level software only and by doing this os can give user process more logical services by making use of interrupts.(like irq0) Also I think ,as I said before, running scheduler in its context in an isolated environment ensures us that it does not interefere with other programs. Do you think that is logical? May I ask the way you implement this very low level task scheduling? Thanx...
http://my.execpc.com/CE/AC/geezer/johnfine/index.htm
I want to avoid irq0 interrupt user process becuase firstly I do not know why I want it that way ??? I mean, I just think that interrupts should be handled bylow level software only and by doing this os can give user process more logical services by making use of interrupts.(like irq0) Also I think ,as I said before, running scheduler in its context in an isolated environment ensures us that it does not interefere with other programs. Do you think that is logical? May I ask the way you implement this very low level task scheduling? Thanx...