System resets if i initialize the stack segment in pmode

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
ggodw000
Member
Member
Posts: 396
Joined: Wed Nov 18, 2015 3:04 pm
Location: San Jose San Francisco Bay Area
Contact:

System resets if i initialize the stack segment in pmode

Post by ggodw000 »

I have working code that if I dont initialize the stack segment and do not touch it during the time system is in protected mode, then system is completely functional.

However I implemented the additional code to save SS:SP in data segment before entering the protected mode and restore it into SS:SP after exiting the protected mode. In that case, the system resets, not sure why. Using jmp$ instruction, I found that reset happens right after enabling the interrupt back after exiting the protected mode.
I checked the stack values before and after by printing it out to screen to see any stack imbalance and no it was just fine. Both before and after values are same. I am wondering what else could be causing it?
Here is snippet of code, the entire code is quite big, so I pasted here the only ones that matter:

THere are two software switches I use to turn on and off the stack preparation and stack loading:

CONFIG_PMODE_SETUP_SS - code that prepares anything related to stack segment so SS:SP can be loaded with valid segments
CONFIG_PMODE_LOAD_SS - actual code that does the loading of SS:SP.

Add'l two switches en/dis-s the IDT preparation and loading of IDT into desc. cache however this is currently both turned off so code inside this switch can be ignored.
CONFIG_PMODE_SETUP_IDT
CONFIG_PMODE_LOAD_IDT
Sorry if it is a lot of code, but that is how i made it to be very configurable code.

Code: Select all

M_ENTER_PMODE macro
    local   mEnterPmodeExit, mEnterPmodeLab1, mEnterPmodeLab2

;   Check if already in protected mode

    IF      OPTION_DEBUG_PMODE
    M_PRINTF "\nM_ENTER_PMODE: Testing to see system is in protected mode."
    ENDIF   ; OPTION_DEBUG_PMODE

    mov     eax, cr0
    test    eax, 01b
    jz      mEnterPmodeLab2

    IF      OPTION_DEBUG_PMODE
    M_PRINTF "\nSystem is in protected-mode. Exit with CX=1."
    ENDIF   ; OPTION_DEBUG_PMODE

    mov     cx, 1
    jmp     mEnterPmodeExit

mEnterPmodeLab2:
    IF      OPTION_DEBUG_PMODE
    M_PRINTF "\nSystem is not in pmode. Checking A20."
    ENDIF   ; OPTION_DEBUG_PMODE

;   A20 gate turned on

    IF      CONFIG_SUPPORT_A20
    jmp     $+2
    in      al, 92h
    or      al, 2h
    out     92h, al
    jmp     $+2
    ENDIF   ; CONFIG_SUPPORT_A20

    IF      OPTION_DEBUG_PMODE
    M_PRINTF "\nChecking pmode initialization flag."
    ENDIF   ; OPTION_DEBUG_PMODE

    cmp     word ptr pModeInitDone, 1
    je      mEnterPmodeLab1

    IF      OPTION_DEBUG_PMODE
    M_PRINTF "\nError. pMode is not initialized."
    ENDIF   ; OPTION_DEBUG_PMODE

    jmp     mEnterPmodeExit

mEnterPmodeLab1:
    IF      OPTION_DEBUG_PMODE
    M_PRINTF "\nSetting gdt ptr."
    ENDIF   ; OPTION_DEBUG_PMODE

    mov     ebx, DATA:offset gdtPtr
    lgdt    fword ptr ds:[ebx]  ; issue LGDT/LIDT instruction.

    IF      CONFIG_PMODE_LOAD_IDT
    mov     ebx, DATA:offset idtPtr
    lidt    fword ptr ds:[ebx]  ; issue LIDT instruction.
    ENDIF   ; CONFIG_PMODE_LOAD_IDT

;   save SS:SP, do not change stack after this!!!
;   while until SS:SP is loaded in p-mode values.

    IF      CONFIG_PMODE_SETUP_SS
    IF      OPTION_DEBUG_PMODE
    M_PRINTF "\nSaving SS SP."
    ENDIF   ; OPTION_DEBUG_PMODE
    mov     si, DATA
    mov     ds, si
    lea     si, DATA:rModeSsSp
    mov     ds:[si], sp
    mov     ds:[si+2], ss
    ENDIF   ; CONFIG_PMODE_SETUP_SS

    push    es
    push    di

    lea     si, DATA:rModeSsSp
    mov     es, ds:[si]
    mov     di, ds:[si+2]

    M_PRINTF "\nSS:SP before exiting pMode: "
    M_PRINT_1616 es, di

    pop     di
    pop     es

;   disable interrupts

    cli

;   Set control register bit.

    mov     eax, cr0
    or      al, 01h
    mov     cr0, eax
    jmp     $+2
    jmp     cs:farJump
farJump:

;   DS = set segment descriptor entry FLAT DATA in GDT

    mov     ax, (flatdata-gdt)
    mov     ds, ax
    jmp     $+2

;   setup protected mode stack segment.

    IF      CONFIG_PMODE_SETUP_SS
    IF      CONFIG_PMODE_LOAD_SS
    mov     ax, (sstack-gdt)
    mov     ss, ax
    mov     sp, 1024

;   mov     0b800h,
;   jmp     $+2
    ENDIF   ; CONFIG_PMODE_LOAD_SS
    ENDIF   ; CONFIG_PMODE_SETUP_SS

;   stack can be changed now.

    IF      CONFIG_PMODE_SETUP_IDT
    IF      CONFIG_PMODE_LOAD_IDT
    sti
    ENDIF   ; CONFIG_PMODE_LOAD_IDT
    ENDIF   ; CONFIG_PMODE_SETUP_IDT

    sub     cx, cx              ; (CX) = indicate successfull entry to pmode.

mEnterPmodeExit:
    ENDM

;   M_EXIT_PMODE macro is used for exiting protected mode.
;   M_ENTER_PMODE is usually followed by M_EXIT_PMODE macro and it is
;   extremely important that if CX=1, then M_EXIT_PMODE macro not be called
;   for obvious reason. Otherwise M_EXIT_PMODE can inadvertently clear
;   CR0[0] which was set and initialized by external O/S not this framework.
;   output: CX=0 - if successfully exited from pmode to real mode.
;           CX=1 - if system was already in real mode or any other failure.

M_EXIT_PMODE macro
    local   mExitPmodeExit, mExitPmodeLab2

    mov     eax, cr0
    test    eax, 01b
    jnz     mExitPmodeLab2
    mov     cx, 1
    jmp     mExitPmodeExit

mExitPmodeLab2:
    IF      CONFIG_PMODE_SETUP_IDT
    IF      CONFIG_PMODE_LOAD_IDT
    cli     ; do not change stack until SS:SP is restored!!!
    ENDIF   ; CONFIG_PMODE_LOAD_IDT
    ENDIF   ; CONFIG_PMODE_SETUP_IDT

;   exit protected mode

    mov     eax, cr0
    and     eax, 0fffffffeh
    mov     cr0, eax

    mov     ax, DATA
    mov     ds, ax

;   save SS:SP, do not change stack after this!!!
;   while until SS:SP is loaded in p-mode values.


    IF      CONFIG_PMODE_SETUP_SS
    mov     si, DATA
    mov     ds, si
    lea     si, DATA:rModeSsSp
    mov     sp, ds:[si]
    mov     ss, ds:[si+2]
    ENDIF   ; CONFIG_PMODE_SETUP_SS

;   turn off A20 gate

    IF      CONFIG_SUPPORT_A20
    jmp     $+2
    in      al, 92h
    and     al, 0feh
    out     92h, al
    jmp     $+2
    ENDIF   ; CONFIG_SUPPORT_A20

;   enable back interrupts

    sti

    push    es
    push    di

    lea     si, DATA:rModeSsSp
    mov     es, ds:[si]
    mov     di, ds:[si+2]

    M_PRINTF "\nSS:SP after exiting pMode: "
    M_PRINT_1616 es, di

    pop     di
    pop     es


    IF      OPTION_DEBUG_PMODE
    M_PRINTF "\nSuccessfully exited from pmode."
    ENDIF   ; OPTION_DEBUG_PMODE

    sub     cx, cx              ; (CX) = indicate success.
mExitPmodeExit:
    ENDM 
Here is the program output if i dont initialize the stack segment during protected mode but still save and restore the SS SP without actually changing the SS:SP, if anything clear let me know:

Code: Select all

Installing gdt to descriptor cache.
Setting up &dt& PTR address:
gdt address: 00007080
gdt ptr Limit | Base:0048:00007080
Installing idt to descriptor cache.
Setting up idt ptr address:
idt address: 000070D0
idt ptr Limit | Base:0800:000070D0
input flat address: 000F56F0
M_ENTER_PMODE: Testing to see system is in protected mode.
System is not in pmode. Checking A20.
Checking pmode initialization flag.
Setting gdt ptr.
Saving SS SP.
SS:SP before exiting pMode: 00E8:06F3
SS:SP after exiting pMode: 00E8:06F3
Successfully exited from pmode.
output: 00010302
1. EBX from getDwordExtMem:00010302
Saving input addr:000F56F4
input flat address: 000F56F4
M_ENTER_PMODE: Testing to see system is in protected mode.
System is not in pmode. Checking A20.
Checking pmode initialization flag.
Setting gdt ptr.
Saving SS SP.
SS:SP before exiting pMode: 00E8:06F3
SS:SP after exiting pMode: 00E8:06F3
Successfully exited from pmode.
output: 00010302
2. EBX from getDwordExtMem:00010302
SS:SP 1a:  06F3:00FE
SS:SP 1b:  06F3:00FE 
Stack segment defined to be 800h size at 1MB using the memory management module (not posted here but guaranteed and bug-free which uses E820 to get available regions)
However i put the all defined descriptor table information below and entry #4 is the stack segment called sstack:

Code: Select all

==============
Descriptor No 00
BX, DS, DI: 0920 0703:08C0
Descriptor. name:  null descriptor
===============:
GDT/LDT Descriptor Info:
---------------:
 00000000:00000000
Segment base:       00000000
Segment size(lim):  00000000
Rx06[7]:     00 - Granularity (0: multiplier 1, 1: multiplier 4K):
Rx06[6]:     00 - Default Rx size: (0: 16-bit, 1: 32-bit):
Rx06[5:4]:   00 - AVL (for O/S use any way):
Rx05[7]:     00 - Present bit: (0: not present, 1: present):
Rx05[6:5]:   00 - DPL(desc.priv.lvl)
  Rx05[4]:   00 - descriptor type (0: system segment, 1: data/code segment):
Rx05[4:1]:   00 - segment descriptor type:
  Rx05[3]:   00 - code/data bit (0: data/stack/non-exec, 1: code segment):
    Rx05[2]: 00 - expansion direction(data)/conform(code) bit:
    data:       0=segment grows up
                1=segment growns down(SS)
    Rx05[1]: 00 - W(data)/R(code)
    data:       0=write access not allowed
                1=write access allowed (read always allowed)
Rx05[0]:     00 - A bit(accessed, each time CPU accesses it)
==============
Descriptor No 01
BX, DS, DI: 0922 0703:08D0
Descriptor. name:  Flat-32 code
===============:
GDT/LDT Descriptor Info:
---------------:
 0000FFFF:00CF9A00
Segment base:       00000000
Segment size(lim):  000FFFFF
Rx06[7]:     01 - Granularity (0: multiplier 1, 1: multiplier 4K):
Rx06[6]:     01 - Default Rx size: (0: 16-bit, 1: 32-bit):
Rx06[5:4]:   00 - AVL (for O/S use any way):
Rx05[7]:     01 - Present bit: (0: not present, 1: present):
Rx05[6:5]:   00 - DPL(desc.priv.lvl)
  Rx05[4]:   01 - descriptor type (0: system segment, 1: data/code segment):
Rx05[4:1]:   0A - segment descriptor type:
  Rx05[3]:   01 - code/data bit (0: data/stack/non-exec, 1: code segment):
    Rx05[2]: 00 - expansion direction(data)/conform(code) bit:
    code:       0=code can only be exec-d from priv.lvl set in ring
                1=code can be exec-d from same or lower priv.level
    Rx05[1]: 01 - W(data)/R(code)
    code:       0=read access not allowed
                1=read access allowed (write access never allowed)
Rx05[0]:     00 - A bit(accessed, each time CPU accesses it)
==============
Descriptor No 02
BX, DS, DI: 0924 0703:08DD
Descriptor. name:  Flat-32 data
===============:
GDT/LDT Descriptor Info:
---------------:
 0000FFFF:00CF9200
Segment base:       00000000
Segment size(lim):  000FFFFF
Rx06[7]:     01 - Granularity (0: multiplier 1, 1: multiplier 4K):
Rx06[6]:     01 - Default Rx size: (0: 16-bit, 1: 32-bit):
Rx06[5:4]:   00 - AVL (for O/S use any way):
Rx05[7]:     01 - Present bit: (0: not present, 1: present):
Rx05[6:5]:   00 - DPL(desc.priv.lvl)
  Rx05[4]:   01 - descriptor type (0: system segment, 1: data/code segment):
Rx05[4:1]:   02 - segment descriptor type:
  Rx05[3]:   00 - code/data bit (0: data/stack/non-exec, 1: code segment):
    Rx05[2]: 00 - expansion direction(data)/conform(code) bit:
    data:       0=segment grows up
                1=segment growns down(SS)
    Rx05[1]: 01 - W(data)/R(code)
    data:       0=write access not allowed
                1=write access allowed (read always allowed)
Rx05[0]:     00 - A bit(accessed, each time CPU accesses it)
==============
Descriptor No 03
BX, DS, DI: 0926 0703:08EA
Descriptor. name:  IDT
===============:
GDT/LDT Descriptor Info:
---------------:
 70D007FF:00009200
Segment base:       000070D0
Segment size(lim):  000007FF
Rx06[7]:     00 - Granularity (0: multiplier 1, 1: multiplier 4K):
Rx06[6]:     00 - Default Rx size: (0: 16-bit, 1: 32-bit):
Rx06[5:4]:   00 - AVL (for O/S use any way):
Rx05[7]:     01 - Present bit: (0: not present, 1: present):
Rx05[6:5]:   00 - DPL(desc.priv.lvl)
  Rx05[4]:   01 - descriptor type (0: system segment, 1: data/code segment):
Rx05[4:1]:   02 - segment descriptor type:
  Rx05[3]:   00 - code/data bit (0: data/stack/non-exec, 1: code segment):
    Rx05[2]: 00 - expansion direction(data)/conform(code) bit:
    data:       0=segment grows up
                1=segment growns down(SS)
    Rx05[1]: 01 - W(data)/R(code)
    data:       0=write access not allowed
                1=write access allowed (read always allowed)
Rx05[0]:     00 - A bit(accessed, each time CPU accesses it)
==============
Descriptor No 04
BX, DS, DI: 0928 0703:08EE
Descriptor. name:  Sstack
===============:
GDT/LDT Descriptor Info:
---------------:
 000007FF:00409610
Segment base:       00100000
Segment size(lim):  000007FF
Rx06[7]:     00 - Granularity (0: multiplier 1, 1: multiplier 4K):
Rx06[6]:     01 - Default Rx size: (0: 16-bit, 1: 32-bit):
Rx06[5:4]:   00 - AVL (for O/S use any way):
Rx05[7]:     01 - Present bit: (0: not present, 1: present):
Rx05[6:5]:   00 - DPL(desc.priv.lvl)
  Rx05[4]:   01 - descriptor type (0: system segment, 1: data/code segment):
Rx05[4:1]:   06 - segment descriptor type:
  Rx05[3]:   00 - code/data bit (0: data/stack/non-exec, 1: code segment):
    Rx05[2]: 01 - expansion direction(data)/conform(code) bit:
    data:       0=segment grows up
                1=segment growns down(SS)
    Rx05[1]: 01 - W(data)/R(code)
    data:       0=write access not allowed
                1=write access allowed (read always allowed)
Rx05[0]:     00 - A bit(accessed, each time CPU accesses it)
==============
Descriptor No 05
BX, DS, DI: 092A 0703:08F5
Descriptor. name:  User code
===============:
GDT/LDT Descriptor Info:
---------------:
 0000FFFF:40C39200
Segment base:       40000000
Segment size(lim):  0003FFFF
Rx06[7]:     01 - Granularity (0: multiplier 1, 1: multiplier 4K):
Rx06[6]:     01 - Default Rx size: (0: 16-bit, 1: 32-bit):
Rx06[5:4]:   00 - AVL (for O/S use any way):
Rx05[7]:     01 - Present bit: (0: not present, 1: present):
Rx05[6:5]:   00 - DPL(desc.priv.lvl)
  Rx05[4]:   01 - descriptor type (0: system segment, 1: data/code segment):
Rx05[4:1]:   02 - segment descriptor type:
  Rx05[3]:   00 - code/data bit (0: data/stack/non-exec, 1: code segment):
    Rx05[2]: 00 - expansion direction(data)/conform(code) bit:
    data:       0=segment grows up
                1=segment growns down(SS)
    Rx05[1]: 01 - W(data)/R(code)
    data:       0=write access not allowed
                1=write access allowed (read always allowed)
Rx05[0]:     00 - A bit(accessed, each time CPU accesses it)
==============
Descriptor No 06
BX, DS, DI: 092C 0703:08FF
Descriptor. name:  User data
===============:
GDT/LDT Descriptor Info:
---------------:
 0000FFFF:80C39200
Segment base:       80000000
Segment size(lim):  0003FFFF
Rx06[7]:     01 - Granularity (0: multiplier 1, 1: multiplier 4K):
Rx06[6]:     01 - Default Rx size: (0: 16-bit, 1: 32-bit):
Rx06[5:4]:   00 - AVL (for O/S use any way):
Rx05[7]:     01 - Present bit: (0: not present, 1: present):
Rx05[6:5]:   00 - DPL(desc.priv.lvl)
  Rx05[4]:   01 - descriptor type (0: system segment, 1: data/code segment):
Rx05[4:1]:   02 - segment descriptor type:
  Rx05[3]:   00 - code/data bit (0: data/stack/non-exec, 1: code segment):
    Rx05[2]: 00 - expansion direction(data)/conform(code) bit:
    data:       0=segment grows up
                1=segment growns down(SS)
    Rx05[1]: 01 - W(data)/R(code)
    data:       0=write access not allowed
                1=write access allowed (read always allowed)
Rx05[0]:     00 - A bit(accessed, each time CPU accesses it)
==============
Descriptor No 07
BX, DS, DI: 092E 0703:0909
Descriptor. name:  Kstack
===============:
GDT/LDT Descriptor Info:
---------------:
 0000FFFF:C04F9610
Segment base:       C0100000
Segment size(lim):  000FFFFF
Rx06[7]:     00 - Granularity (0: multiplier 1, 1: multiplier 4K):
Rx06[6]:     01 - Default Rx size: (0: 16-bit, 1: 32-bit):
Rx06[5:4]:   00 - AVL (for O/S use any way):
Rx05[7]:     01 - Present bit: (0: not present, 1: present):
Rx05[6:5]:   00 - DPL(desc.priv.lvl)
  Rx05[4]:   01 - descriptor type (0: system segment, 1: data/code segment):
Rx05[4:1]:   06 - segment descriptor type:
  Rx05[3]:   00 - code/data bit (0: data/stack/non-exec, 1: code segment):
    Rx05[2]: 01 - expansion direction(data)/conform(code) bit:
    data:       0=segment grows up
                1=segment growns down(SS)
    Rx05[1]: 01 - W(data)/R(code)
    data:       0=write access not allowed
                1=write access allowed (read always allowed)
Rx05[0]:     00 - A bit(accessed, each time CPU accesses it)
==============
Descriptor No 08
BX, DS, DI: 0930 0703:08C0
Descriptor. name:  null descriptor
===============:
GDT/LDT Descriptor Info:
---------------:
 0000FFFF:C04F9620
Segment base:       C0200000
Segment size(lim):  000FFFFF
Rx06[7]:     00 - Granularity (0: multiplier 1, 1: multiplier 4K):
Rx06[6]:     01 - Default Rx size: (0: 16-bit, 1: 32-bit):
Rx06[5:4]:   00 - AVL (for O/S use any way):
Rx05[7]:     01 - Present bit: (0: not present, 1: present):
Rx05[6:5]:   00 - DPL(desc.priv.lvl)
  Rx05[4]:   01 - descriptor type (0: system segment, 1: data/code segment):
Rx05[4:1]:   06 - segment descriptor type:
  Rx05[3]:   00 - code/data bit (0: data/stack/non-exec, 1: code segment):
    Rx05[2]: 01 - expansion direction(data)/conform(code) bit:
    data:       0=segment grows up
                1=segment growns down(SS)
    Rx05[1]: 01 - W(data)/R(code)
    data:       0=write access not allowed
                1=write access allowed (read always allowed)
Rx05[0]:     00 - A bit(accessed, each time CPU accesses it)
key takeaway after spending yrs on sw industry: big issue small because everyone jumps on it and fixes it. small issue is big since everyone ignores and it causes catastrophy later. #devilisinthedetails
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: System resets if i initialize the stack segment in pmode

Post by Brendan »

Hi,

Which language is this code written in (I've never seen it before)?

Could you compile the code, and post a disassembly of it so that it's possible to see what it does?

Note: If there's a choice, I'd prefer a disassembly from NDISASM. I've been using NASM/NDISASM for 15+ years so I'm much more comfortable with its assembly syntax. 8)


Thanks,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
ggodw000
Member
Member
Posts: 396
Joined: Wed Nov 18, 2015 3:04 pm
Location: San Jose San Francisco Bay Area
Contact:

Re: System resets if i initialize the stack segment in pmode

Post by ggodw000 »

there are couple of helper macros mostly for printing register content and strings to aid in debugging used throughout the code. If I disassemble, then expansion of those macros will make it even for more harder to see what is going on. And there is one single software switch I can use to turn off all those macros and result is not impacted. Instead I re-pasted the same code but remove all macro statements (since they are redundant) and all other code for which it is disabled (so not compiled) through software switch:
Is it better now?

Code: Select all

;   Check if already in protected mode

...

mEnterPmodeLab1:
    mov     ebx, DATA:offset gdtPtr
    lgdt    fword ptr ds:[ebx]  ; issue LGDT/LIDT instruction.

;   save SS:SP, do not change stack after this!!!
;   while until SS:SP is loaded in p-mode values.

    mov     si, DATA
    mov     ds, si
    lea     si, DATA:rModeSsSp
    mov     ds:[si], sp
    mov     ds:[si+2], ss

;   disable interrupts

    cli

;   Set control register bit.

    mov     eax, cr0
    or      al, 01h
    mov     cr0, eax
    jmp     $+2
    jmp     cs:farJump
farJump:

;   DS = set segment descriptor entry FLAT DATA in GDT

    mov     ax, (flatdata-gdt)
    mov     ds, ax
    jmp     $+2

;   setup protected mode stack segment.

    mov     ax, (sstack-gdt)
    mov     ss, ax
    mov     sp, 1024

;   stack can be changed now.

;   sti

; ... do your stuff in protected mode. 

;   cli     ; do not change stack until SS:SP is restored!!!

;   exit protected mode

    mov     eax, cr0
    and     eax, 0fffffffeh
    mov     cr0, eax

    mov     ax, DATA
    mov     ds, ax

;   Stack can be changed after restore. 

    mov     si, DATA
    mov     ds, si
    lea     si, DATA:rModeSsSp
    mov     sp, ds:[si]
    mov     ss, ds:[si+2]

;   enable back interrupts

    sti <-- SYSTEM RESETS RIGHT AFTER THIS and NOT BEFORE!!! 

mExitPmodeExit:
    
Last edited by ggodw000 on Thu Jan 07, 2016 4:52 am, edited 3 times in total.
key takeaway after spending yrs on sw industry: big issue small because everyone jumps on it and fixes it. small issue is big since everyone ignores and it causes catastrophy later. #devilisinthedetails
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: System resets if i initialize the stack segment in pmode

Post by iansjack »

It sounds like something is altering your stack or the real mode interrupt vectors. M_PRINTF is a black box - are you sure that it doesn't alter anything?

Run the code under a debugger and single-step; you should then see what is being altered, and what is doing it.
ggodw000
Member
Member
Posts: 396
Joined: Wed Nov 18, 2015 3:04 pm
Location: San Jose San Francisco Bay Area
Contact:

Re: System resets if i initialize the stack segment in pmode

Post by ggodw000 »

iansjack wrote:It sounds like something is altering your stack or the real mode interrupt vectors. M_PRINTF is a black box - are you sure that it doesn't alter anything?

Run the code under a debugger and single-step; you should then see what is being altered, and what is doing it.
all printf switches can be turned off without impacting behavior. if i do not change the SS:SP but still saves and restores the SS:SP and prints them out then SS:SP is exacly same before and after.
The PRINTF macro has been used so much, it does not alter any register. I placed the arrows below where i printed out the SS:SP b4 and after entering pmode.
Single step unfortunately not work because system reset right after enabling the STI and can not be used the when it is in pmode since IDT is not working.

Code: Select all

Installing gdt to descriptor cache.
Setting up &dt& PTR address:
gdt address: 00007080
gdt ptr Limit | Base:0048:00007080
Installing idt to descriptor cache.
Setting up idt ptr address:
idt address: 000070D0
idt ptr Limit | Base:0800:000070D0
input flat address: 000F56F0
M_ENTER_PMODE: Testing to see system is in protected mode.
System is not in pmode. Checking A20.
Checking pmode initialization flag.
Setting gdt ptr.
Saving SS SP.
SS:SP before exiting pMode: 00E8:06F3 <---
SS:SP after exiting pMode: 00E8:06F3 <---
Successfully exited from pmode.
output: 00010302
1. EBX from getDwordExtMem:00010302
Saving input addr:000F56F4
input flat address: 000F56F4
M_ENTER_PMODE: Testing to see system is in protected mode.
System is not in pmode. Checking A20.
Checking pmode initialization flag.
Setting gdt ptr.
Saving SS SP.
SS:SP before exiting pMode: 00E8:06F3 <---
SS:SP after exiting pMode: 00E8:06F3 <---
Successfully exited from pmode.
output: 00010302
2. EBX from getDwordExtMem:00010302
SS:SP 1a:  06F3:00FE <---
SS:SP 1b:  06F3:00FE <---
key takeaway after spending yrs on sw industry: big issue small because everyone jumps on it and fixes it. small issue is big since everyone ignores and it causes catastrophy later. #devilisinthedetails
Octocontrabass
Member
Member
Posts: 5587
Joined: Mon Mar 25, 2013 7:01 pm

Re: System resets if i initialize the stack segment in pmode

Post by Octocontrabass »

ggodw000 wrote:Single step unfortunately not work because system reset right after enabling the STI and can not be used the when it is in pmode since IDT is not working.
You don't need an IDT to use the Bochs debugger. (Or any other emulator's debugger, for that matter.)
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: System resets if i initialize the stack segment in pmode

Post by iansjack »

I can recommend SimNow ( http://developer.amd.com/tools-and-sdks ... simulator/ ) as a very able simulator/debugger for debugging an OS at an assembler level. As stated, there is no need for a valid IDT - or anything else - for it to do its work. Just set a breakpoint early in your code and get single-stepping. You'll probably learn a lot about what is happening.
ggodw000
Member
Member
Posts: 396
Joined: Wed Nov 18, 2015 3:04 pm
Location: San Jose San Francisco Bay Area
Contact:

Re: System resets if i initialize the stack segment in pmode

Post by ggodw000 »

ok thx, let s see what happens if i give it a try.
key takeaway after spending yrs on sw industry: big issue small because everyone jumps on it and fixes it. small issue is big since everyone ignores and it causes catastrophy later. #devilisinthedetails
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: System resets if i initialize the stack segment in pmode

Post by Brendan »

Hi,
ggodw000 wrote:Is it better now?
Yes.

Code: Select all

;   Check if already in protected mode

...

mEnterPmodeLab1:
    mov     ebx, DATA:offset gdtPtr
    lgdt    fword ptr ds:[ebx]  ; issue LGDT/LIDT instruction.

;   save SS:SP, do not change stack after this!!!
;   while until SS:SP is loaded in p-mode values.

    mov     si, DATA
    mov     ds, si
    lea     si, DATA:rModeSsSp
    mov     ds:[si], sp
    mov     ds:[si+2], ss

;   disable interrupts

    cli

;   Set control register bit.

    mov     eax, cr0
    or      al, 01h
    mov     cr0, eax
See note below (about NMIs).

Code: Select all

    jmp     $+2
    jmp     cs:farJump
farJump:
This piece isn't even valid assembly (the "jmp cs:farJump" should cause "error: invalid combination of opcode and operands" from NASM).

If it was valid assembly (e.g. you replaced it with something more like "jmp (flatcode-gdt):farJump") then I think your code segment is 32-bit and you don't tell the assembler you've switch to 32-bit code (e.g. the "bits 32" directive), and that will cause bizarre problems.

Code: Select all

;   DS = set segment descriptor entry FLAT DATA in GDT

    mov     ax, (flatdata-gdt)
    mov     ds, ax
    jmp     $+2

;   setup protected mode stack segment.

    mov     ax, (sstack-gdt)
    mov     ss, ax
    mov     sp, 1024
Given that (I assume) you're supposed to be using 32-bit protected mode code here; you should do "mov esp,1024". If ESP happened to contain (e.g.) the value 0xEFEF1234 in real mode, then real mode only uses the lowest half of it (SP = 0x1234) which would work fine, but in 32-bit code all of ESP is used and after your "mov sp,1024" you'd end up with ESP=0xEFEF0400 and not ESP=1024.

Code: Select all

;   stack can be changed now.

    sti
If any interrupt occurs after this "STI" (while you're in protected mode) you will get undefined behaviour because you don't have a sane IDT and the CPU will use the old IVT (which contains 4-byte "real mode segment:offset" entries) as if it's an IDT (with 8-byte entries). If you're lucky it will crash. If you're unlucky it will do random/unexpected things (execute garbage).

Note: After the "see note" point marked above (just after the "mov cr0, eax" to enable protected mode) there's a (very small) risk of an NMI occurring and causing the same "random/unexpected behaviour". To guard against this I'd recommend disabling IRQs, loading an IDT with limit=0, then enabling protected mode, then loading your protected mode IDT after. This ensures that (for "NMI at worst possible time") you get a guaranteed triple fault with no chance of "random/unexpected behaviour" (which seems excessive, but is the only sane option given that NMI typically indicates hardware failure and therefore shouldn't be ignored, and that there's no way you can be expected to do anything more).

That's the only bugs I could find.

There's also this "less efficient" piece (loading DS with the same thing twice):

Code: Select all

    mov     ax, DATA
    mov     ds, ax

;   Stack can be changed after restore. 

    mov     si, DATA
    mov     ds, si
Mostly; I can't see anything that would explain the symptoms you've reported (it should crash long before it ever reaches the last STI).


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
ggodw000
Member
Member
Posts: 396
Joined: Wed Nov 18, 2015 3:04 pm
Location: San Jose San Francisco Bay Area
Contact:

Re: System resets if i initialize the stack segment in pmode

Post by ggodw000 »

OK thanks, pretty good catching. the enabling of INT in pmode is part is actually not there, i should have not pasted and I will correct this post if possible.
i am going to try esp, this might be very plausible culprit.
jmp cs:farjump so far it worked pretty good i am using masm32, however i will take a note of it.

amd's simnow is very sweet, i am running the compiled binary from fdd image and same hyper-v floppy image can be used, which is much less headache and i get triple-fault:

Code: Select all

GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
FDD: Could not open floppy image Y:/tmp/p1.vfd
FDD: Could not open floppy image Y:/tmp/p1.vfd
FDD: Could not open floppy image Y:/tmp/p1.vfd
FDD: Could not open floppy image Y:/tmp/p1.vfd

GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
GH: EnableCf8ExtCfg bit set in IOCF8, but ECS not enabled.
cisc-cpu.cpp: CProcessor::GenerateException(): shutdown due to triple fault

Fatal error reached, stopping simulation.  Error message(s) follow:

cisc-cpu.cpp: CProcessor::GenerateException(): shutdown due to triple fault

NOTE:  Simulation cannot be restarted until a reset is asserted.
Simulation state CAN be inspected with the SimNow debugger.
key takeaway after spending yrs on sw industry: big issue small because everyone jumps on it and fixes it. small issue is big since everyone ignores and it causes catastrophy later. #devilisinthedetails
User avatar
Brendan
Member
Member
Posts: 8561
Joined: Sat Jan 15, 2005 12:00 am
Location: At his keyboard!
Contact:

Re: System resets if i initialize the stack segment in pmode

Post by Brendan »

Hi,
ggodw000 wrote:jmp cs:farjump so far it worked pretty good i am using masm32, however i will take a note of it.
Sorry - I just assumed it was NASM. I have no idea what masm32 does with instructions that the CPU itself doesn't support (maybe it just pretends its a normal short/near jump and ignores the "CS:", and maybe it gives it a pointless CS override prefix - either way it's not what you intended).
ggodw000 wrote:

Code: Select all

Simulation state CAN be inspected with the SimNow debugger.
You'd want to obtain "SimNow debugger" and inspect it (to find out why it crashed), and/or use something like (e.g.) Bochs where it tells you why it crashed.

For example, Bochs spits out something like this (at the end of its log):

Code: Select all

02052658988p[CPU0 ] >>PANIC<< exception(): 3rd (13) exception with no resolution
02052658988i[CPU0 ] CPU is in protected mode (active)
02052658988i[CPU0 ] CS.mode = 32 bit
02052658988i[CPU0 ] SS.mode = 32 bit
02052658988i[CPU0 ] | EAX=0002c000  EBX=00000000  ECX=00000000  EDX=40013900
02052658988i[CPU0 ] | ESP=c000783c  EBP=00000000  ESI=c00067b4  EDI=00000000
02052658988i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf af pf CF
02052658988i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
02052658988i[CPU0 ] |  CS:0010( 0002| 0|  0) 00000000 ffffffff 1 1
02052658988i[CPU0 ] |  DS:002b( 0005| 0|  3) 00000000 ffffffff 1 1
02052658988i[CPU0 ] |  SS:0018( 0003| 0|  0) 00000000 ffffffff 1 1
02052658988i[CPU0 ] |  ES:002b( 0005| 0|  3) 00000000 ffffffff 1 1
02052658988i[CPU0 ] |  FS:0000( 0000| 0|  0) 00000000 00000000 0 0
02052658988i[CPU0 ] |  GS:0000( 0000| 0|  0) 00000000 00000000 0 0
02052658988i[CPU0 ] | EIP=c000644c (c000644c)
02052658988i[CPU0 ] | CR0=0xe0000011 CR2=0xa0000c00 CR3=0x0002c000
02052658988i[CPU0 ] 0xc000644c>> mov ebx, dword ptr ds:[ebp*4-1610609664] : 8B1CAD000C00A0
02052658988i[CMOS ] Last time is 1452164487 (Thu Jan  7 21:31:27 2016)
02052658988i[XGUI ] Exit
02052658988i[     ] restoring default signal behavior
02052658988i[CTRL ] quit_sim called with exit code 1
You can imagine how useful this would be for figuring out what happened.


Cheers,

Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
User avatar
iansjack
Member
Member
Posts: 4706
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: System resets if i initialize the stack segment in pmode

Post by iansjack »

Brendan wrote:You'd want to obtain "SimNow debugger"
The debugger is built in to SimNow and offers very comprehensive facilities for debugging.
ggodw000
Member
Member
Posts: 396
Joined: Wed Nov 18, 2015 3:04 pm
Location: San Jose San Francisco Bay Area
Contact:

Re: System resets if i initialize the stack segment in pmode

Post by ggodw000 »

i had very bad experience with bochs, spent hours trying to setup bootable disk and never worked. that was like another project. may be if simnow can not do more comprehensive output then i may try bosh one more time again.
if possible, i'd like to use amd sim and yesterday i got it up and running in less than few minutes. i am still exploring.

thx!
key takeaway after spending yrs on sw industry: big issue small because everyone jumps on it and fixes it. small issue is big since everyone ignores and it causes catastrophy later. #devilisinthedetails
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: System resets if i initialize the stack segment in pmode

Post by Combuster »

ggodw000 wrote:i had very bad experience with bochs, spent hours trying to setup bootable disk and never worked.
Maybe you should try knowing a bit better what you're doing before you go and do it. Primarily, your posts seem to indicate that you tend to avoid reading the manuals. If bochs doesn't boot the most likely case is that you either did not read that, or you try something that wouldn't always work on real hardware either.
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
ggodw000
Member
Member
Posts: 396
Joined: Wed Nov 18, 2015 3:04 pm
Location: San Jose San Francisco Bay Area
Contact:

Re: System resets if i initialize the stack segment in pmode

Post by ggodw000 »

Combuster wrote:
ggodw000 wrote:i had very bad experience with bochs, spent hours trying to setup bootable disk and never worked.
Maybe you should try knowing a bit better what you're doing before you go and do it. Primarily, your posts seem to indicate that you tend to avoid reading the manuals. If bochs doesn't boot the most likely case is that you either did not read that, or you try something that wouldn't always work on real hardware either.
there was not much to read, obviously the technical manual said to place the fdd object in the installation directory and it does not take much to indicate pathways in its boshsrc or whatever setting file. obviously other people has toiled and had it working, it is just my opinion that i had no liking of the way it presents its UI/UX.

Secondly, whynot just tell me what i am missing then
Last edited by ggodw000 on Sat Jan 09, 2016 4:09 am, edited 2 times in total.
key takeaway after spending yrs on sw industry: big issue small because everyone jumps on it and fixes it. small issue is big since everyone ignores and it causes catastrophy later. #devilisinthedetails
Post Reply