Skip to content

Commit 3a00f17

Browse files
committed
[kernel] Kernel HMA enhancements, fixes and cleanups
1 parent 9c59551 commit 3a00f17

File tree

7 files changed

+295
-323
lines changed

7 files changed

+295
-323
lines changed

tlvc/arch/i86/boot/crt0.S

-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@
1010
.extern start_kernel
1111
.global early_putchar
1212

13-
#ifdef CONFIG_HMA_KERNEL
1413
jmp _start // 16byte filler to move entry point to the
1514
.word 0,0,0,0,0,0,0 // ... start of the HMA
16-
#endif
1715
_start:
1816

1917
/*

tlvc/arch/i86/boot/setup.S

+90-133
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,9 @@
6262
! ...
6363
! 0x1e2: part_offset long Sector offset of booted MBR partition
6464
! 0x1e6: elks_magic long "ELKS", written by build tool
65-
| 0x1ea: xms_kbytes word Size of XMS memory in Kbytes
66-
! 0x1ea-0x1ee: 5 bytes UNUSED
65+
! 0x1ea: xms_kbytes word size of xms memory in kbytes
66+
! 0x1ec: hma_kernel byte hma=kernel seen in /bootopts
67+
! 0x1ed-0x1ee: 2 bytes UNUSED
6768
! 0x1ef: SETUPSEG word UNUSED
6869
! 0x1f1: setup_sects byte in 512-byte sectors, written by build tool
6970
! 0x1f2: ROOTFLAGS word UNUSED
@@ -81,8 +82,6 @@
8182
#include <linuxmt/boot.h>
8283

8384
// Relocating loader debug option
84-
// NOTE: If running the kernel in HMA, setup hangs when jumping to the kernel if
85-
// debug_output is active and serial_output is NOT active.
8685
debug_output = 0 // display various register values during execution
8786
serial_output = 0 // use INT 14 serial instead of INT 10 console out
8887
debug_loader = 0 // display relocations
@@ -481,11 +480,11 @@ sys_hdr_msg:
481480

482481
sys_hdr_good:
483482
mov %sp,%bp
484-
mov 8,%dx // -2(%bp) code (text) size
483+
mov 8,%dx // -2(%bp) .text code size
485484
push %dx
486485
add $15,%dx // align on next paragraph (issue #209)
487486
mov $4,%cl
488-
shr %cl,%dx // DX = code size in paragraph
487+
shr %cl,%dx // DX = code size in paragraphs
489488
shr %cl,%bx // BX = header size in paragraphs
490489

491490
mov 12,%ax // -4(%bp) data size
@@ -512,49 +511,31 @@ sys_hdr_good:
512511
add %bx,%ax // skip header
513512
mov %ax,%ds
514513
xor %si,%si
514+
xor %di,%di
515515

516-
push %ds
517-
mov $SETUP_DATA,%ax
518-
mov %ax,%ds
519-
mov $0x8800,%ax
520-
int $0x15 // get xms size
521-
jc no_xms
522-
mov %ax,(xms_kbytes)
523-
pop %ds
524-
#ifdef CONFIG_HMA_KERNEL
525-
cmp $64,%ax
526-
jl no_xms
527-
mov $0x2401,%ax
528-
int $0x15 // Set a20
529-
jnc 2f
530-
call set_a20
531-
call verify_a20
532-
jc no_xms
533-
2:
516+
#ifdef CONFIG_ARCH_IBMPC
517+
// Check whether relocating .text to HMA is possible
518+
call checkhma
519+
jc 2f // no HMA
534520
mov $HMA_SEG,%ax
535521
jmp 1f
536522
#endif
537-
no_xms:
538-
movw $0,(xms_kbytes)
539-
pop %ds
540-
mov $REL_SYSSEG,%ax
541-
1:
542-
mov %ax,%es
523+
2: mov $REL_SYSSEG,%ax
524+
1: mov %ax,%es
543525
mov %ax,-18(%bp) // save .text segment
544526
.ifeq debug_output
545527
call hex4sp
546528
.endif
547529

548-
add %dx,%ax // add code paragraphs = .fartext start
549-
#ifdef CONFIG_HMA_KERNEL
550-
jnc 1f // skip if it didn't overflow (no HMA)
551-
movw $REL_SYSSEG,%ax // .fartext start here
552-
1:
553-
#endif
554-
mov %ax,-20(%bp) // save .data start in case no .fartext
555-
xor %di,%di
556-
557530
mov -2(%bp),%cx // code size in bytes
531+
add %dx,%ax // add code paragraphs = .fartext start
532+
jnc 1f // skip if didn't overflow (no HMA)
533+
mov $REL_SYSSEG,%ax // .fartext starts at normal .text location
534+
add $16,%si // skip first paragraph at FFFF:0000
535+
add $16,%di
536+
sub $16,%cx
537+
1: mov %ax,-20(%bp) // save .data start in case no .fartext
538+
558539
.hex4sp %ds,"\nCopy DEF_SYSSEG .text to REL_SYSSEG DS:"
559540
.hex4sp %si,"SI:"
560541
.hex4sp %es,"ES:"
@@ -594,12 +575,9 @@ no_xms:
594575

595576
mov -18(%bp),%ax // kernel .text segment
596577
add %dx,%ax // skip code paragraphs
597-
#ifdef CONFIG_HMA_KERNEL
598578
jnc 1f
599-
mov $REL_SYSSEG,%ax // if text in HMA, start fartext here
600-
#endif
601-
1:
602-
mov %ax,%es
579+
mov $REL_SYSSEG,%ax // if text in HMA, start fartext here
580+
1: mov %ax,%es
603581
mov %ax,-20(%bp) // save .fartext segment
604582
xor %di,%di
605583

@@ -735,7 +713,7 @@ data_reloc:
735713
.hex4sp %cx,"entry:"
736714
.if debug_output
737715
.ifeq serial_output // if not serial output
738-
mov $debug_prompt, %ax
716+
mov $debug_prompt,%ax
739717
call csputs
740718
xor %ah,%ah // read key press
741719
int $0x16
@@ -839,6 +817,9 @@ csputs: push %bx
839817
jmp 1b
840818
2: pop %bx
841819
ret
820+
821+
debug_prompt:
822+
.ascii "\r\nPress key to boot: \0"
842823
.endif
843824

844825
// Output hex nibble, byte and word. All registers saved.
@@ -883,11 +864,7 @@ hex4sp: call hex4
883864
ret
884865

885866
hello_mess:
886-
.ascii "\r\nTLVC Setup \0"
887-
.if debug_output
888-
debug_prompt:
889-
.ascii "\r\nPress key to boot: \0"
890-
.endif
867+
.ascii "\r\nELKS Setup \0"
891868

892869
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
893870
// Architecture specific routines for IBM PC
@@ -906,89 +883,6 @@ arch_get_mem:
906883
#endif
907884
ret
908885

909-
// A20 handlers - from unreal.c
910-
// Even quite modern BIOSes don't support the A20 INT15 calls (QEMU does)
911-
// set_a20: Attempt to set the A20 line on 286 and higher
912-
// verify_a20: Check that a20 is set/working
913-
914-
#ifdef CONFIG_HMA_KERNEL
915-
set_a20:
916-
pushf # save interrupt status
917-
cli # interrupts off
918-
call empty_8042
919-
mov $0xD0,%al # 8042 command byte to read output port
920-
out %al,$0x64
921-
1: in $0x64,%al
922-
test $1,%al # output buffer (data _from_ keyboard) full?
923-
jz 1b # no, loop
924-
925-
in $0x60,%al # read output port
926-
or %ah,%ah
927-
jne 2f
928-
and $0xFD,%al # AND ~2 to disable
929-
jmp 3f
930-
2: or $2,%al # OR 2 to enable
931-
3: mov %al,%ah
932-
933-
call empty_8042
934-
mov $0xD1,%al # 8042 command byte to write output port
935-
out %al,$0x64
936-
937-
call empty_8042
938-
mov %ah,%al # the value to write
939-
out %al,$0x60
940-
941-
call empty_8042
942-
popf # restore interrupt status
943-
ret
944-
945-
0: jmp 1f # a delay (probably not effective nor necessary)
946-
1: jmp 2f
947-
2: in $0x60,%al # read and discard data/status from 8042
948-
empty_8042:
949-
jmp 1f
950-
1: jmp 2f # delay
951-
2: in $0x64,%al
952-
test $1,%al # output buffer (data _from_ keyboard) full?
953-
jnz 0b # yes, read and discard
954-
test $2,%al # input buffer (data _to_ keyboard) empty?
955-
jnz empty_8042 # no, loop
956-
ret
957-
958-
// verify if A20 gate is enabled, return 0 if disabled
959-
verify_a20:
960-
push %ds
961-
push %es
962-
963-
xor %ax,%ax
964-
mov %ax,%ds
965-
dec %ax
966-
mov %ax,%es
967-
968-
pushf # save interrupt status
969-
cli # interrupts off
970-
971-
mov %es:0x10,%ax # read word at FFFF:0010 (1 meg)
972-
not %ax # 1's complement
973-
pushw 0 # save word at 0000:0000 (0)
974-
975-
mov %ax,0 # word at 0 = ~(word at 1 meg)
976-
mov 0,%ax # read it back
977-
cmp %es:0x10,%ax # fail if word at 0 == word at 1 meg
978-
979-
popw 0
980-
981-
jz 1f # if ZF=1, the A20 gate is NOT enabled
982-
clc # no carry: OK
983-
9: popf # restore interrupt status
984-
pop %es
985-
pop %ds
986-
ret
987-
1: stc # Carry - error
988-
jmp 9b
989-
990-
#endif
991-
992886
// Set INITSEG values for IBM PC
993887
// Determine display type using INT 10h AH=12 and INT 10h AH=1A
994888
// Get display page and mode using INT 10h AH=0F
@@ -1035,12 +929,72 @@ novga: mov %al,14 // CGA 25 rows
1035929
mov %ax,%ds
1036930
call arch_get_mem // save base memory size
1037931
mov %ax,mem_kbytes
932+
mov $0x8800,%ax // get xms size
933+
int $0x15
934+
jc 1f
935+
mov %ax,xms_kbytes
1038936

1039937
#ifdef CONFIG_BOOTOPTS
1040938
call bootopts // load /bootopts into DEF_OPTSEG (0050:0000)
939+
call hmabootopts // check /bootopts for hma=kernel
940+
mov %al,hma_kernel
1041941
#endif
1042942
ret
1043943

944+
// check for hma=kernel in /bootopts, return AX = 0 if not
945+
hmabootopts:
946+
push %ds
947+
push %es
948+
949+
push %cs // ES = our code segment
950+
pop %es
951+
mov $DEF_OPTSEG,%ax // DS:SI = /bootopts in memory
952+
mov %ax,%ds
953+
954+
xor %si,%si // look for hma=kernel in /bootopts segment
955+
look: mov (%si),%al // done when NUL seen
956+
test %al,%al
957+
jz 1f
958+
mov $hma_string,%di
959+
mov $11,%cx
960+
push %si
961+
repz
962+
cmpsb // %ds:(%si) with %es:(%di)
963+
pop %si
964+
inc %si
965+
test %cx,%cx
966+
jnz look // NZ = no match
967+
mov $'H',%ax
968+
call putc
969+
jmp 2f
970+
1: xor %ax,%ax // no HMA
971+
2: pop %es
972+
pop %ds
973+
ret
974+
975+
hma_string:
976+
.ascii "\nhma=kernel" // size = 11
977+
978+
// check whether HMA can be enabled, return NC if so with A20 enabled
979+
checkhma:
980+
push %ds
981+
mov $INITSEG,%ax
982+
mov %ax,%ds
983+
mov xms_kbytes,%ax //. must have xms size >= 64k
984+
cmp $64,%ax
985+
jl 1f
986+
mov hma_kernel,%al // and hma=kernel in /bootopts
987+
test %al,%al
988+
jz 1f
989+
call enable_a20_gate // and A20 enabled
990+
test %ax,%ax
991+
jz 1f
992+
clc // success
993+
jmp 2f
994+
1: stc // fail
995+
2: pop %ds
996+
ret
997+
1044998
// Write AL to console, save all registers
1045999
putc: push %ax
10461000
push %bx
@@ -1068,6 +1022,9 @@ putc: push %ax
10681022
// TODO: remove and use alternate mechanism for XT vs AT BIOS capabilities
10691023
#include "cputype.S"
10701024

1025+
// include code to enable/verify A20 address gate
1026+
#include "../lib/a20.inc"
1027+
10711028
#endif /* CONFIG_ARCH_IBMPC*/
10721029

10731030

0 commit comments

Comments
 (0)