Przejscie w tryb wirtualny w 386 EX



Masz problem? Zapytaj na forum elektroda.pl z bramk± pl.misc.elektronika!

Poprzedni Następny
Wiadomość
spis tre¶ci
From: Przemyslaw Bazarnik <bazarnik_at_nospam_comarch.pl>
Subject: Przejscie w tryb wirtualny w 386 EX
Date: Fri, 06 Feb 1998 13:17:25 +0100


Czesc

Mam system wbudowany (zdecydowanie bardziej wole termin embedded :-))
z Intelem 386EX (zwykly 386 plus io, timery etc) i problem :-):

Co chce osiagnac:
najprostszy, najszybszy i zajmujacy najmniej pamieci sposob przejscia
do trybu wirtualnego (po resecie) z 32-bitowym modelem flat:
CS, DS obejmuja calosc przestrzeni adresowej, adresy fizyczne = adresy
logiczne, bez stronnicowania.
(Wymagania darmowego real-time OSa: RTEMS http://www.rtems.com/)

Pytanie:
Czy do przejscia w tryb wirtualny i zladowania segmentu kodu 32-bitowego
(segment USE32) konieczne jest wykonanie przelaczenia zadania?
(Skoku do TSS albo task gate'a??)

Z moich dotycczasowych doswiadczen wynika ze prosty skok
miedzysegmentowy (po wejsciu w tryb wirtualny) do takiego segmentu
(USE32) konczy sie zawieszeniem systemu.

Uzywam narzedzi GNU jako crosskompilatora (gcc, binutils, etc pod
linuxem, target: i386-coff).

Wszelkie sugestie (przykladowy kod? :-)) mile widziane!

Przemek



PS Dla ciekawych fragment kodu:

(skladnia gas)

/*
... setup the 386EX ICU
*/

/* setup GDT */

/* clear the GDT space */

xorl eax,eax /* value to clear out memory */
movw ax, es /* and ram base */
movl $ SYM (_Global_descriptor_table), edi


cld /* make direction flag count up */
movl $ GDT_size,ecx
repne /* while ecx != 0 */
stosb /* clear a byte */



/* GDT entires setup: */

/* Macro args format:
(desc_table_start_addr, desc_no, type, dpl, base_addr, limit,
granularity_bit) */

rtime_set_seg_desc( SYM (_Global_descriptor_table), MICE_CODE_SEG_DESC,
0x1a, 0, 0xfc000, 0xfffff, 1) /* flat code segment */
rtime_set_seg_desc( SYM (_Global_descriptor_table), MICE_DATA_SEG_DESC,
0x12, 0, 0, 0xfffff, 1) /* flat data segment */
set_seg_desc( SYM (_Global_descriptor_table), SAB_BASE_DATA_SEG_DESC,
0x12, 0, 0x78000, 0xfffff, 1) /* SAB base segment */
rtime_tss_set_seg_desc(SYM (_Global_descriptor_table),
INIT_TSS_386_SEG_DESC, 0x09, 0, SYM (_minit_dummy_tss), TSS_386_SIZE, 0)
/* dummy tss */
set_seg_desc( SYM (_Global_descriptor_table), EXCEPTION_CODE_SEG_DESC,
0x1a, 0, 0, 0xfffff, 1) /* exception flat code segment */



/* IDT entires setup */

/* clear the IDT space */

xorl eax,eax /* value to clear out memory */
movw ax, es /* and ram base */
movl $ SYM (Interrupt_descriptor_table), edi

cld /* make direction flag count up */
movl $ IDT_size,ecx
repne /* while ecx != 0 */
stosb /* clear a byte */


/* #define gate_set_desc( desc_table_sym, desc_no, type, dpl, selector,
offset) */
/* #define rtime_gate_set_desc( desc_table_sym, desc_no, type, dpl,
selector, offset)
*/

/*
for task gate type = 0x05
interrupt gate type = 0x0e
trap gate type = 0x0f
*/

rtime_gate_set_desc( SYM (Interrupt_descriptor_table), 0, 0x0e, 0,
EXCEPTION_CODE_SEG_DESC*8, SYM( _minit_exception0 ))





/* setup GDTR */

movw $ GDT_size-1, ax
movw ax, SYM (_mice_GDTR ) + DTR_LIMIT(,1)

movl $ SYM (_Global_descriptor_table), eax
movl eax, SYM (_mice_GDTR ) + DTR_BASE(,1)


/* setup IDTR */

movw $ IDT_size-1, ax
movw ax, SYM (_mice_IDTR ) + DTR_LIMIT(,1)

movl $ SYM (Interrupt_descriptor_table), eax
movl eax, SYM (_mice_IDTR ) + DTR_BASE(,1)



/* check */
movw SYM (_Global_descriptor_table)+8+1(,1), bx
notw bx
movb bl, fs:PVRC(,1)
movb bh, fs:PVRA(,1)



/* load GDT */
lgdt SYM (_mice_GDTR ) (,1)


/* enter protected mode CPL =0 */


movl $ 0x0001, eax
movl eax, %cr0


PUBLIC( prot_switch_flush )

/* clear prefetch queue */
jmp SYM( prot_switch_flush )
SYM( prot_switch_flush ):


/* switched to protected: do not change the GNU as 32 bit mode
since we are still in default code segment */


/* load IDT */
lidt SYM (_mice_IDTR ) (,1)


/* load dummy task register */

movw $ INIT_TSS_386 SEG_DESC8, ax
ltr ax


/* load descriptors */

/* reload cs */
/* direct intersegment jump */
/* coded manually to overcome 16-bit code GNU as limitations */

#ifdef ___NO_NO
.byte 0x66 /* operand size prefix 32-bit*/
.byte 0xea /* direct far jmp */
.long SYM(prot_cs_reload) /* IP - continue from SYM(prot_cs_reload)
in 32-bit c seg*/
.hword 8*MICE_CODE_SEG_DESC /* CS */
#endif



PUBLIC(prot_cs_reload)
SYM(prot_cs_reload):



/* Load data desc */
movw $ (MICE_DATA_SEG_DESC*8), bx /* data seg */
movw bx, ds /* RAM flat desc */


/* setup the stack - equal to DS */
movw bx, ss
movl $ 0x2000, esp


/* SAB base desc */
movw $ (SAB_BASE_DATA_SEG_DESC*8), bx
movw bx, es /* SAB base flat desc */



/* test the stack */

push ax
pop ax /* works */





/* programm ICU */
/* use C code in bspstartup */



/* start.s replacement code HERE: */

/* Do not jump to start.s */
/* jump to the start (lib/start/i386/start.s - RTEMS cpu dependent init
code ) */
/* jmp SYM (start) */

Poprzedni Następny
Wiadomość
spis tre¶ci
Date: Fri, 06 Feb 1998 13:35:05 +0100
From: Adam Bienias <souadam_at_nospam_polbox.com.pl>
Subject: Re: Przejscie w tryb wirtualny w 386 EX


Przemyslaw Bazarnik wrote:

Czesc

Mam system wbudowany (zdecydowanie bardziej wole termin embedded :-))
z Intelem 386EX (zwykly 386 plus io, timery etc) i problem :-):

Co chce osiagnac:
najprostszy, najszybszy i zajmujacy najmniej pamieci sposob przejscia
do trybu wirtualnego (po resecie) z 32-bitowym modelem flat:
CS, DS obejmuja calosc przestrzeni adresowej, adresy fizyczne = adresy
logiczne, bez stronnicowania.
(Wymagania darmowego real-time OSa: RTEMS http://www.rtems.com/)

Pytanie:
Czy do przejscia w tryb wirtualny i zladowania segmentu kodu 32-bitowego
(segment USE32) konieczne jest wykonanie przelaczenia zadania?
(Skoku do TSS albo task gate'a??)

Z moich dotycczasowych doswiadczen wynika ze prosty skok
miedzysegmentowy (po wejsciu w tryb wirtualny) do takiego segmentu
(USE32) konczy sie zawieszeniem systemu.


W trybie flat, dla ulatwienia sprawy, tworzy sie tylko jeden segment
kodu i jeden danych. Segment danych pokrywa sie z segmentem kodu, lecz
posiada inny atrybut (seg.danych, a nie kodu).
Przy przelaczaniu sie v386<->real nie potrzeba zmieniac zadania, chyba
ze tryb real jest emulowany jako v86.

Poprzedni Następny
Wiadomość
spis tre¶ci
From: dobrov_at_nospam_friko.onet.pl (Arkadiusz Dabrowski)
Subject: Re: Przejscie w tryb wirtualny w 386 EX
Date: Sat, 07 Feb 1998 16:29:32 GMT


On Fri, 06 Feb 1998 13:17:25 +0100, Przemyslaw Bazarnik
<bazarnik_at_nospam_comarch.pl> wrote:

Czesc

Mam system wbudowany (zdecydowanie bardziej wole termin embedded :-))
z Intelem 386EX (zwykly 386 plus io, timery etc) i problem :-):

Co chce osiagnac:
najprostszy, najszybszy i zajmujacy najmniej pamieci sposob przejscia
do trybu wirtualnego (po resecie) z 32-bitowym modelem flat:
CS, DS obejmuja calosc przestrzeni adresowej, adresy fizyczne = adresy
logiczne, bez stronnicowania.
(Wymagania darmowego real-time OSa: RTEMS http://www.rtems.com/)

Pytanie:
Czy do przejscia w tryb wirtualny i zladowania segmentu kodu 32-bitowego
(segment USE32) konieczne jest wykonanie przelaczenia zadania?
(Skoku do TSS albo task gate'a??)

Z moich dotycczasowych doswiadczen wynika ze prosty skok
miedzysegmentowy (po wejsciu w tryb wirtualny) do takiego segmentu
(USE32) konczy sie zawieszeniem systemu.


Nie pojalem sie analizy twojego kodu, bo wystepuje w nim nieczytelna dla
mnie notacja asemblerowa.

Jesli chodzi o skok do segmentu 32-bitowego, to ja realizuje to w
nastepujacy sposob:

push dword ptr ROM_CODE_SEG shl 3 ; ROM_CODE_SEG to stala (equ)
push offset start_32 ; etykieta w segmencie 32 bitowym (use32)
db 066h ; zeby wymusic pobranie 32-bitowego offsetu
retf

Mozna to tez chyba zrobic w sposob nastepujacy (w tasm lub wasm):


jmp pword ptr start_32

Etykieta powinna byc wtedy zdefiniowana nastepujaco:

start_32 label far

Przy wykonywaniu takiego skoku absolutnie zbedne jest przelacznie zadan.
Wykonuje sie normalny, daleki skok do segmentu kodu.


Jezeli po skoku program ci sie zawiesza to przyczyny moga byc nastepujace:
1. Blednie wykonany skok (skaczesz gdzie indziej niz myslisz).
2. Blad w deskryptorze segmentu kodu.
3. Tablica deskryptorow jest gdzie indziej niz myslisz (zawartosc gdtr).
4. Przepelnienie stosu lub null_selector w rejestrze SS - jezeli skaczesz
za posrednictwem stosu.
5. Skaczesz do segmentu o nieprawidlowym poziomie ochrony.
Jezeli segment, do ktorego skaczesz jest zwyklym segmentem kodu, to poziom
jego ochrony musi byc rowny poziomowi ochrony segmentu, z ktorego skaczesz
(czyli zapewne 0).
6. Brak pamieci RAM.
Byc moze o tym wiesz, ale i tak napisze. 386ex ma specjalny uklad do
wybierania pamieci i urzadzen i/o (Chip Selects Unit - CSU). Systemy oparte
na tym procesorze maja zwykle pamiec ram wybierana innym sygnalem procesora
niz pamiec ROM (zeby nie budowac zewnetrznego dekodera adresow). ROM jest
wybierany przez sygnal UCS domyslnie aktywny po resecie i obejmujacy cala
przestrzen adresowa. Wszystkie inne CS-y sa nieaktywne, wiec pamiec ram
podlaczona do ktoregos z nich po resecie jest niewidoczna.
Jezeli o tym nie wiesz, to moge ci napisac bardziej szczegolowo.

+--\ /--\ +--\ +--\ /--\ | | Arkadiusz Dabrowski
| | | | |--< |--/ | | | | dobrov_at_nospam_priv.onet.pl
+--/ \--/ +--/ | \ \--/ \/ stare konto:
dobrov_at_nospam_zeus.polsl.gliwice.pl