[OpenBIOS] r799 - dev/geode
svn at openbios.org
svn at openbios.org
Thu Jan 31 11:15:59 CET 2008
Author: wmb
Date: 2008-01-31 11:15:58 +0100 (Thu, 31 Jan 2008)
New Revision: 799
Modified:
dev/geode/smi.fth
Log:
Geode SMI handler - the code is pretty tight now, using only one page of SMM RAM.
Modified: dev/geode/smi.fth
===================================================================
--- dev/geode/smi.fth 2008-01-31 05:16:56 UTC (rev 798)
+++ dev/geode/smi.fth 2008-01-31 10:15:58 UTC (rev 799)
@@ -9,74 +9,65 @@
previous definitions
-h# 4000.0000 constant smm-base
-h# 1.0000 constant smm-size
+h# f.f000 constant smm-base
+h# 1000 constant smm-size \ We use about 3K of this, 2K for stacks
: +smm ( offset -- adr ) smm-base + ;
-h# 30 constant /smm-gdt
-smm-size h# 100 -
-dup constant smm-stack
-dup constant smm-save-gdt 8 +
-dup constant smm-gdtp 8 +
-dup constant smm-gdt /smm-gdt +
-dup constant smm-pdir la1+
+h# 28 constant /smm-gdt
+
+\ The handler code takes about h# 140 bytes
+
+\ The following save area + the SMM_HEADER (h# 30) takes about h# 100
+h# 200
+dup constant smm-save-gdt 8 +
+dup constant smm-gdtp 8 +
+dup constant smm-gdt /smm-gdt +
+dup constant smm-pdir la1+
dup constant smm-forth-origin la1+
dup constant smm-forth-up la1+
+dup constant smm-forth-entry la1+
-dup constant smm-code16 h# a +
-dup constant smm-data16 h# a +
-dup constant smm-code32 h# a +
-dup constant smm-data32 h# a +
-dup constant smm-ds h# a +
-dup constant smm-es h# a +
-dup constant smm-fs h# a +
-dup constant smm-gs h# a +
-dup constant smm-ss h# a +
-dup constant smm-cs h# a +
-dup constant smm-esp la1+
-dup constant smm-sp wa1+
-drop
+\ 10 bytes for each of 6 segment registers
+dup constant smm-save-seg d# 60 +
+dup constant smm-save-esp la1+
+dup constant smm-sp la1+
+ \ 8x 4-byte general registers + config adr + cs3 + spare
+h# 38 + constant smm-stack
-: set-descr ( base limit d.type sel offset -- )
- +smm 2>r format-descriptor ( d.descr r: sel adr )
- 2r@ 8 + w! ( d.descr r: sel adr )
- 2dup r> d! ( d.descr r: sel )
- r> smm-gdt + +smm d! ( )
+h# 300 constant smm-header
+
+: set-descr ( base limit d.type sel -- )
+ >r format-descriptor ( d.descr r: sel )
+ r> smm-gdt + +smm d! ( )
;
: set-smm-descs ( -- )
- smm-base -1 code32 format-descriptor smm-gdt 8 + +smm d! \ Boosted code32
-
- smm-base smm-size 1- code16 h# 10 smm-code16 set-descr
- smm-base smm-size 1- data16 h# 18 smm-data16 set-descr
- 0 -1 code32 h# 20 smm-code32 set-descr
- 0 -1 data32 h# 28 smm-data32 set-descr
- /smm-gdt 1- smm-gdtp +smm w! \ GDT limit
+\ smm-base -1 code32 format-descriptor smm-gdt 8 + +smm d! \ Boosted code32
+ smm-base smm-size 1- code16 h# 08 set-descr
+ smm-base smm-size 1- data16 h# 10 set-descr
+ 0 -1 code32 h# 18 set-descr
+ 0 -1 data32 h# 20 set-descr
+ /smm-gdt 1- smm-gdtp +smm w! \ GDT limit
smm-gdt +smm smm-gdtp +smm wa1+ l! \ GDT base
;
nuser smi-sp0
nuser smi-rp0
-defer smi-return
-: smi-exec ( -- )
- ." Forth SMI handler" cr
- quit
- smi-return
-;
label smm-handler
16-bit
- cs: ds smm-ds #) svdc
- cs: smm-data16 #) ds rsdc \ Now we have a data segment
+ cs: ds smm-save-seg d# 00 + #) svdc
+ cs: smm-gdt h# 10 + #) ds rsdc \ Now we have a data segment
+ es smm-save-seg d# 10 + #) svdc
+ fs smm-save-seg d# 20 + #) svdc
+ gs smm-save-seg d# 30 + #) svdc
+ ss smm-save-seg d# 40 + #) svdc
+ cs smm-save-seg d# 50 + #) svdc \ So we can get back to the boost segment
- es smm-es #) svdc
- fs smm-fs #) svdc
- gs smm-gs #) svdc
- ss smm-ss #) svdc
- smm-data16 #) ss rsdc \ Now we have a data segment
+ smm-gdt h# 10 + #) ss rsdc
- op: sp smm-esp #) mov
+ op: sp smm-save-esp #) mov
smm-stack # sp mov \ Now we have a stack
op: pusha
@@ -88,30 +79,18 @@
cr3 ax mov op: ax push
sp smm-sp #) mov
-\ ---
\ Get into protected mode using the same segments
\ Don't bother with the IDT; we won't enable interrupts
op: smm-save-gdt #) sgdt
op: smm-gdtp #) lgdt
-\ Test<
- \ Get into the 4G flat code-32 address space
- cs smm-cs #) svdc \ So we can get back
- smm-code32 #) cs rsdc \ 4G flat address space for code
+ cr0 ax mov 1 # al or ax cr0 mov \ Enter protected mode
+ op: here 7 + smm-handler - +smm h# 18 #) far jmp
32-bit
- here 5 + +smm #) jmp \ Into unboosted segment
-nop nop nop nop nop nop nop
-
- cr0 ax mov 1 # al or ax cr0 mov \ Enter protected mode
- here 2 + #) jmp
-
\ Reload segment registers with protected mode bits
- cs: smm-data32 +smm #) ds rsdc
- smm-data32 +smm #) ss rsdc
- smm-data32 +smm #) es rsdc
- smm-data32 +smm #) fs rsdc
- smm-data32 +smm #) gs rsdc
+ op: h# 20 # ax mov
+ ax ds mov ax es mov ax fs mov ax gs mov ax ss mov
\ Turn on paging
smm-pdir +smm #) ax mov
@@ -121,6 +100,7 @@
\ Beginning of Forth-specific stuff
smm-forth-origin +smm #) bx mov
smm-forth-up +smm #) up mov
+ smm-forth-entry +smm #) ip mov
\ Exchange the stack and return stack pointer with the smi versions
'user sp0 sp mov
@@ -132,13 +112,10 @@
sp 'user sp0 mov
rp 'user rp0 mov
- \ Set the interpreter pointer
- 'body smi-exec origin - # ip mov
- bx ip add \ add current origin
cld
c;
-code (smi-return)
+code (smi-return) \ This code field must be relocated after copying to SMM memory
\ Exchange the stack and return stack pointer with the smi versions
'user sp0 sp mov
'user rp0 rp mov
@@ -149,30 +126,24 @@
sp 'user sp0 mov
rp 'user rp0 mov
-\ End of Forth-specific stuff
+ \ End of Forth-specific stuff
\ Turn off paging
cr0 ax mov h# 8000.0000 invert # ax and ax cr0 mov \ Turn off Paging Enable bit
cr0 ax mov 1 invert # al and ax cr0 mov \ Enter real mode
- here 2 + #) jmp
-
- \ Reload segment registers with real mode bits
- cs: smm-data16 +smm #) ss rsdc
- cs: smm-data16 +smm #) ds rsdc
-
-
\ Return to the boosted code-16 address space
- smm-cs #) cs rsdc
+ smm-save-seg d# 50 + +smm #) cs rsdc
16-bit
- here 2 + #) jmp \ 16-bit JMP zeros EIP[31:16]
+ op: here 5 + smm-base - #) jmp \ Decrease IP while increasing the segment register
-\ >Test
+ \ Reload data segment registers
+ cs: smm-gdt h# 10 + #) ss rsdc
+ cs: smm-gdt h# 10 + #) ds rsdc
op: smm-save-gdt #) lgdt
-\ ---
smm-sp #) sp mov
op: ax pop ax cr3 mov
@@ -182,86 +153,74 @@
op: popa
- op: smm-esp #) sp mov
+ op: smm-save-esp #) sp mov
- smm-ss #) ss rsdc
- smm-gs #) gs rsdc
- smm-fs #) fs rsdc
- smm-es #) es rsdc
- smm-ds #) ds rsdc
+ smm-save-seg d# 40 + #) ss rsdc
+ smm-save-seg d# 30 + #) gs rsdc
+ smm-save-seg d# 20 + #) fs rsdc
+ smm-save-seg d# 10 + #) es rsdc
+ smm-save-seg d# 00 + #) ds rsdc
rsm
end-code
here smm-handler - constant /smm-handler
+: smi-return ( -- ) [ ' (smi-return) smm-handler - +smm ] literal execute ;
+defer handle-smi ' noop is handle-smi
+create smm-exec ] handle-smi smi-return [
+
: setup-smi ( -- )
- \ Map the SMM region to physical memory at e.0000
+ \ This is how you would map the SMM region to physical memory at 4000.0000
\ This is a Base Mask Offset descriptor - the base address
\ is 4000.0000 and to that is added the offset c00e.0000
\ to give the address 000e.0000 in the GLMC address space.
- \ The mask is ffff.0000 , i.e. 64K
- h# 2.c00e0.40000.ffff0. h# 1000.0026 msr!
+ \ The mask is ffff.f000 , i.e. 4K
- \ Put 64K SMM memory at 4000.0000 in the processor linear address space
+ \ This is unnecessary if the SMM memory is in a region that is
+ \ already mapped with a descriptor
+ \ h# 2.c00e0.40000.fffff. h# 1000.0026 msr!
+
+ \ Put 4K SMM memory at 000f.f000 in the processor linear address space
\ Cacheable in SMM mode, non-cacheable otherwise
- h# 4000f.0.00.40000.1.01. h# 180e msr!
+ \ Depends on smm-base and smm-size
+ h# 000ff.0.00.000ff.1.01. h# 180e msr!
\ Base Limit
\ smm-base smm-size 1- h# 133b msr!
+ \ The limit here must be large enough to cover the code address
+ \ between the time that we reenter real mode and the time we
+ \ reestablish the boosted descriptor.
smm-base -1 h# 133b msr! \ Big limit
- smm-base smm-size + 0 h# 132b msr! \ Offset of SMM Header
+ smm-base smm-header + 0 h# 132b msr! \ Offset of SMM Header
h# 18. h# 1301 msr! \ Enable IO and software SMI
- smm-base dup smm-size -1 mmu-map
+ \ Unnecessary if already in mapped memory
+ \ smm-base dup smm-size -1 mmu-map
smm-handler smm-base /smm-handler move
+ \ Relocate the code field of the code word that is embedded in the sequence
['] (smi-return) smm-handler - +smm ( cfa-adr )
dup ta1+ swap token!
set-smm-descs
cr3@ smm-pdir +smm l!
+
origin smm-forth-origin +smm l!
+ smm-exec smm-forth-entry +smm l!
up@ smm-forth-up +smm l!
- h# 1000 +smm smi-sp0 !
- h# 2000 +smm smi-rp0 !
+ h# 800 +smm smi-sp0 !
+ h# c00 +smm smi-rp0 !
;
-: do-smi-return ( -- )
- ['] (smi-return) smm-handler - +smm execute
-;
-' do-smi-return is smi-return
+: smi-interact ( -- ) ." In SMI" cr quit ;
+' smi-interact is handle-smi
+
: enable-virtual-pci ( -- )
h# 5000.2012 msr@ swap h# 8002 or swap h# 5000.2002 msr! \ Virtualize devices f and 1
h# 5000.2002 msr@ swap 8 invert and swap h# 5000.2002 msr! \ Enable SSMI for config accesses
;
-
-code smi smint ax push c;
-
-\ Forth stuff
-[ifdef] notyet
-[then]
-
-[ifdef] notyet
-XXX code to return from Forth
-[then]
-
-[ifdef] notyet
- \ We are running in a segment that is identity mapped
- cr0 ax mov h# 8000.0000 invert # ax and ax cr0 mov \ Turn off Paging Enable bit
-[then]
-
-label emita
- op: dx dx xor dx dx xor
- h# 3fd # dx mov
- begin dx al in h# 20 # al and 0<> until
- h# 41 # al mov h# f8 # dl mov al dx out
- begin again
-\ h# 3fd # dx mov
-\ begin dx al in h# 20 # al and 0<> until
-end-code
-here emita - constant /emita
-: puta ( adr -- ) emita swap /emita move ;
+code smi smint c;
More information about the OpenBIOS
mailing list