Add infrastructure to support access to .data16 (and .text16) variables

from protected-mode code.

Set up %ds to point to .data16 in prot_to_real, so that code specified
via REAL_EXEC() and friends can access variables in .data16.

Move most real-mode librm variables from .text16 to .data16.
pull/1/head
Michael Brown 2006-05-04 23:14:06 +00:00
parent f4429533a6
commit 832807726a
2 changed files with 124 additions and 75 deletions

View File

@ -336,6 +336,7 @@ install_prealloc:
call install_highmem call install_highmem
/* Continue executing in .text16 segment */ /* Continue executing in .text16 segment */
movw %bx, %ds
pushw %cs pushw %cs
pushw $2f pushw $2f
pushw %ax pushw %ax
@ -344,11 +345,11 @@ install_prealloc:
.section ".text16", "awx", @progbits .section ".text16", "awx", @progbits
1: 1:
/* Set up protected-mode GDT, call relocate(), reset GDT */ /* Set up protected-mode GDT, call relocate(), reset GDT */
call init_gdt call init_librm
pushl $relocate pushl $relocate
data32 call prot_call data32 call prot_call
addw $4, %sp addw $4, %sp
call init_gdt call init_librm
/* Return to executing in .prefix section */ /* Return to executing in .prefix section */
lret lret

View File

@ -24,7 +24,7 @@
/**************************************************************************** /****************************************************************************
* Global descriptor table * Global descriptor table
* *
* Call init_gdt to set up the GDT before attempting to use any * Call init_librm to set up the GDT before attempting to use any
* protected-mode code. * protected-mode code.
* *
* Define FLATTEN_REAL_MODE if you want to use so-called "flat real * Define FLATTEN_REAL_MODE if you want to use so-called "flat real
@ -45,7 +45,7 @@
#else #else
#define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x00 #define RM_LIMIT_16_19__AVL__SIZE__GRANULARITY 0x00
#endif #endif
.section ".text16" .section ".data16", "aw", @progbits
.align 16 .align 16
gdt: gdt:
gdt_limit: .word gdt_length - 1 gdt_limit: .word gdt_length - 1
@ -86,56 +86,71 @@ gdt_end:
.equ gdt_length, gdt_end - gdt .equ gdt_length, gdt_end - gdt
/**************************************************************************** /****************************************************************************
* init_gdt (real-mode near call, 16-bit real-mode return address) * init_librm (real-mode near call, 16-bit real-mode return address)
* *
* Initialise the GDT ready for transitions to protected mode. * Initialise the GDT ready for transitions to protected mode.
* *
* Parameters: * Parameters:
* %edi : Physical base of protected-mode code * %cs : .text16 segment
* %ds : .data16 segment
* %edi : Physical base of protected-mode code (virt_offset)
**************************************************************************** ****************************************************************************
*/ */
.section ".text16" .section ".text16"
.code16 .code16
.globl init_gdt .globl init_librm
init_gdt: init_librm:
/* Preserve registers */ /* Preserve registers */
pushl %eax pushl %eax
pushw %bx pushl %ebx
/* Record virt_offset */ /* Store _virt_offset and set up virtual_cs and virtual_ds segments */
movl %edi, %cs:virt_offset_rm_copy
/* Set virtual_cs and virtual_ds base */
movl %edi, %eax movl %edi, %eax
movw $virtual_cs, %bx movw $virtual_cs, %bx
call set_seg_base call set_seg_base
movw $virtual_ds, %bx
call set_seg_base
movl %edi, _virt_offset
/* Set real_cs and real_ds base, and GDT base */ /* Negate virt_offset */
movw $real_cs, %bx negl %edi
/* Store rm_cs and _text16, set up real_cs segment */
xorl %eax, %eax xorl %eax, %eax
movw %cs, %ax movw %cs, %ax
movw %ax, rm_cs
shll $4, %eax shll $4, %eax
movw $real_cs, %bx
call set_seg_base call set_seg_base
leal (%eax, %edi), %ebx
movl %ebx, _text16
/* Store rm_ds and _data16, set up real_ds segment and set GDT base */
xorl %eax, %eax
movw %ds, %ax
movw %ax, %cs:rm_ds
shll $4, %eax
movw $real_ds, %bx
call set_seg_base
leal (%eax, %edi), %ebx
movl %ebx, _data16
addl $gdt, %eax addl $gdt, %eax
movl %eax, %cs:gdt_base movl %eax, gdt_base
/* Restore registers */ /* Restore registers */
popw %bx negl %edi
popl %ebx
popl %eax popl %eax
ret ret
.section ".text16" .section ".text16"
.code16 .code16
set_seg_base: set_seg_base:
pushl %eax 1: movw %ax, 2(%bx)
movw %ax, %cs:(0+2)(%bx) rorl $16, %eax
movw %ax, %cs:(8+2)(%bx) movb %al, 4(%bx)
shrl $16, %eax movb %ah, 7(%bx)
movb %al, %cs:(0+4)(%bx) roll $16, %eax
movb %al, %cs:(8+4)(%bx)
movb %ah, %cs:(0+7)(%bx)
movb %ah, %cs:(8+7)(%bx)
popl %eax
ret ret
/**************************************************************************** /****************************************************************************
@ -157,19 +172,25 @@ set_seg_base:
.section ".text16" .section ".text16"
.code16 .code16
real_to_prot: real_to_prot:
/* Protected-mode return address => %ebx */ /* Make sure we have our data segment available */
popl %ebx movw %cs:rm_ds, %ax
movw %ax, %ds
/* Real-mode %cs => %dx, %ss => %bp */ /* Add _virt_offset, _text16 and _data16 to stack to be
movw %cs, %dx * copied, and also copy the return address.
*/
pushl _virt_offset
pushl _text16
pushl _data16
addw $16, %cx /* %ecx must be less than 64kB anyway */
/* Real-mode %ss:%sp => %bp:%esi */
movw %ss, %bp movw %ss, %bp
movzwl %sp, %esi
/* virt_offset => %edi */
movl %cs:virt_offset_rm_copy, %edi
/* Switch to protected mode */ /* Switch to protected mode */
cli cli
data32 lgdt %cs:gdt data32 lgdt gdt
movl %cr0, %eax movl %cr0, %eax
orb $CR0_PE, %al orb $CR0_PE, %al
movl %eax, %cr0 movl %eax, %cr0
@ -184,24 +205,24 @@ real_to_prot:
movw %ax, %fs movw %ax, %fs
movw %ax, %gs movw %ax, %gs
/* Record virt_offset */
movl %edi, virt_offset
/* Move data from RM stack to PM stack and set up PM stack */ /* Move data from RM stack to PM stack and set up PM stack */
movzwl %sp, %esi
movl pm_esp, %esp movl pm_esp, %esp
subl %ecx, %esp subl %ecx, %esp
movl %esp, %edi movl %esp, %edi
rep ss movsb rep ss movsb
movw %ax, %ss movw %ax, %ss
/* Record real-mode %cs and %ss:sp */ /* Record real-mode %ss:sp (after removal of data) */
movw %dx, rm_cs
movw %bp, rm_ss movw %bp, rm_ss
movw %si, rm_sp movw %si, rm_sp
/* Publish virt_offset, text16 and data16 for PM code to use */
popl data16
popl text16
popl virt_offset
/* Return to virtual address */ /* Return to virtual address */
jmp *%ebx ret
/**************************************************************************** /****************************************************************************
* prot_to_real (protected-mode near call, 32-bit real-mode return address) * prot_to_real (protected-mode near call, 32-bit real-mode return address)
@ -209,9 +230,9 @@ real_to_prot:
* Switch from 32-bit protected mode with virtual addresses to 16-bit * Switch from 32-bit protected mode with virtual addresses to 16-bit
* real mode. The protected-mode %esp is stored in pm_esp and the * real mode. The protected-mode %esp is stored in pm_esp and the
* real-mode %ss:sp is restored from the saved rm_ss and rm_sp. All * real-mode %ss:sp is restored from the saved rm_ss and rm_sp. All
* real-mode data segment registers are set equal to %ss. Interrupts * real-mode data segment registers are loaded from the saved rm_ds.
* are *not* enabled, since we want to be able to use prot_to_real in * Interrupts are *not* enabled, since we want to be able to use
* an ISR. All other registers may be destroyed. * prot_to_real in an ISR. All other registers may be destroyed.
* *
* The return address for this function should be a 32-bit (sic) * The return address for this function should be a 32-bit (sic)
* real-mode offset within .code16. * real-mode offset within .code16.
@ -224,15 +245,15 @@ real_to_prot:
.section ".text" .section ".text"
.code32 .code32
prot_to_real: prot_to_real:
/* Real-mode return address => %ebx */ /* Add return address to data to be moved to RM stack */
popl %ebx addl $4, %ecx
/* Real-mode %ss:sp => %ebp:edx */ /* Real-mode %ss:sp => %ebp:edx */
movzwl rm_ss, %ebp movzwl rm_ss, %ebp
movzwl rm_sp, %edx movzwl rm_sp, %edx
subl %ecx, %edx subl %ecx, %edx
/* Copy data from PM stack to RM stack */ /* Move data from PM stack to RM stack */
movl %ebp, %eax movl %ebp, %eax
shll $4, %eax shll $4, %eax
leal (%eax,%edx), %edi leal (%eax,%edx), %edi
@ -240,12 +261,9 @@ prot_to_real:
movl %esp, %esi movl %esp, %esi
rep movsb rep movsb
/* Record protected-mode %esp */ /* Record protected-mode %esp (after removal of data) */
movl %esi, pm_esp movl %esi, pm_esp
/* Real-mode %cs => %di */
movw rm_cs, %di
/* Load real-mode segment limits */ /* Load real-mode segment limits */
movw $REAL_DS, %ax movw $REAL_DS, %ax
movw %ax, %ds movw %ax, %ds
@ -257,27 +275,40 @@ prot_to_real:
.section ".text16" .section ".text16"
.code16 .code16
1: 1:
/* Set up real-mode ljmp instruction */
movw %di, %ds:(p2r_ljmp + 3)
/* Switch to real mode */ /* Switch to real mode */
movl %cr0, %eax movl %cr0, %eax
andb $0!CR0_PE, %al andb $0!CR0_PE, %al
movl %eax, %cr0 movl %eax, %cr0
ljmp *p2r_jump_vector
p2r_jump_target:
p2r_ljmp: /* Set up real-mode stack */
ljmp $0, $1f /* Segment is filled in by above code */
1:
/* Set up real-mode stack and data segments, and stack pointer */
movw %bp, %ds
movw %bp, %es
movw %bp, %fs
movw %bp, %gs
movw %bp, %ss movw %bp, %ss
movw %dx, %sp movw %dx, %sp
/* Set up real-mode data segments */
movw %cs:rm_ds, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
/* Return to real-mode address */ /* Return to real-mode address */
jmp *%bx data32 ret
/* Real-mode code and data segments. Assigned by the call to
* init_librm. rm_cs doubles as the segment part of the jump
* vector used by prot_to_real. rm_ds is located in .text16
* rather than .data16 because code needs to be able to locate
* the data segment.
*/
.section ".data16"
p2r_jump_vector:
.word p2r_jump_target
rm_cs: .word 0
.section ".text16"
rm_ds: .word 0
/**************************************************************************** /****************************************************************************
* prot_call (real-mode near call, 32-bit real-mode return address) * prot_call (real-mode near call, 32-bit real-mode return address)
@ -406,11 +437,12 @@ real_call:
/* Construct call to real-mode function */ /* Construct call to real-mode function */
movw %sp, %bp movw %sp, %bp
movw RC_OFFSET_FUNCTION(%bp), %ax movw RC_OFFSET_FUNCTION(%bp), %ax
movw %ax, %cs:rc_function movw %ax, rc_function
/* Call real-mode function */ /* Call real-mode function */
popal popal
call *%cs:rc_function call *RC_OFFSET_FUNCTION(%esp)
call *rc_function
pushal pushal
/* Switch to protected mode and move register dump back to PM stack */ /* Switch to protected mode and move register dump back to PM stack */
@ -427,7 +459,9 @@ real_call:
popal popal
ret ret
.section ".text16"
/* Function vector, used because */
.section ".data16"
rc_function: .word 0 rc_function: .word 0
/**************************************************************************** /****************************************************************************
@ -464,19 +498,33 @@ rc_function: .word 0
* to us. * to us.
**************************************************************************** ****************************************************************************
*/ */
.section ".data" .section ".data"
.globl rm_sp .globl rm_sp
rm_sp: .word 0 rm_sp: .word 0
.globl rm_ss .globl rm_ss
rm_ss: .word 0 rm_ss: .word 0
.globl rm_cs
rm_cs: .word 0
.globl pm_esp .globl pm_esp
pm_esp: .long _estack pm_esp: .long _estack
.section ".text16" /****************************************************************************
virt_offset_rm_copy: .long 0 * Virtual address offsets
*
* These are used by the protected-mode code to map between virtual
* and physical addresses, and to access variables in the .text16 or
* .data16 segments.
****************************************************************************
*/
/* Internal copies, created by init_librm (which runs in real mode) */
.section ".data16"
_virt_offset: .long 0
_text16: .long 0
_data16: .long 0
/* Externally-visible copies, created by real_to_prot */
.section ".data" .section ".data"
.globl virt_offset .globl virt_offset
virt_offset: .long 0 virt_offset: .long 0
.globl text16
text16: .long 0
.globl data16
data16: .long 0