Procházet zdrojové kódy

[pcbios] Don't use "lret $2" to return from an interrupt

Using "lret $2" to return from an interrupt causes interrupts to be
disabled in the calling program, since the INT instruction will have
disabled interrupts.  Instead, patch CF on the stack and use iret to
return.

Interestingly, the original PC BIOS had this bug in at least one
place.

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Michael Brown <mcb30@etherboot.org>
tags/v0.9.8
H. Peter Anvin před 15 roky
rodič
revize
f44205b9ea

+ 18
- 9
src/arch/i386/firmware/pcbios/e820mangler.S Zobrazit soubor

@@ -489,6 +489,18 @@ get_mangled_e820:
489 489
 	ret
490 490
 	.size get_mangled_e820, . - get_mangled_e820
491 491
 
492
+/****************************************************************************
493
+ * Set/clear CF on the stack as appropriate, assumes stack is as it should
494
+ * be immediately before IRET
495
+ ****************************************************************************
496
+ */
497
+patch_cf:
498
+	pushw	%bp
499
+	movw	%sp, %bp
500
+	setc	8(%bp)	/* Set/reset CF; clears PF, AF, ZF, SF */
501
+	popw	%bp
502
+	ret
503
+
492 504
 /****************************************************************************
493 505
  * INT 15,e820 handler
494 506
  ****************************************************************************
@@ -500,7 +512,8 @@ int15_e820:
500 512
 	popw	%ds
501 513
 	call	get_mangled_e820
502 514
 	popw	%ds
503
-	lret	$2
515
+	call	patch_cf
516
+	iret
504 517
 	.size int15_e820, . - int15_e820
505 518
 	
506 519
 /****************************************************************************
@@ -512,7 +525,7 @@ int15_e801:
512 525
 	/* Call previous handler */
513 526
 	pushfw
514 527
 	lcall	*%cs:int15_vector
515
-	pushfw
528
+	call	patch_cf
516 529
 	/* Edit result */
517 530
 	pushw	%ds
518 531
 	pushw	%cs:rm_ds
@@ -524,9 +537,7 @@ int15_e801:
524 537
 	xchgw	%ax, %cx
525 538
 	xchgw	%bx, %dx
526 539
 	popw	%ds
527
-	/* Restore flags returned by previous handler and return */
528
-	popfw
529
-	lret	$2
540
+	iret
530 541
 	.size int15_e801, . - int15_e801
531 542
 	
532 543
 /****************************************************************************
@@ -538,16 +549,14 @@ int15_88:
538 549
 	/* Call previous handler */
539 550
 	pushfw
540 551
 	lcall	*%cs:int15_vector
541
-	pushfw
552
+	call	patch_cf
542 553
 	/* Edit result */
543 554
 	pushw	%ds
544 555
 	pushw	%cs:rm_ds
545 556
 	popw	%ds
546 557
 	call	patch_1m
547 558
 	popw	%ds
548
-	/* Restore flags returned by previous handler and return */
549
-	popfw
550
-	lret	$2
559
+	iret
551 560
 	.size int15_88, . - int15_88
552 561
 		
553 562
 /****************************************************************************

+ 3
- 2
src/arch/i386/firmware/pcbios/fakee820.c Zobrazit soubor

@@ -63,6 +63,8 @@ void fake_e820 ( void ) {
63 63
 			      "cmpl $0x534d4150, %%edx\n\t"
64 64
 			      "jne 99f\n\t"
65 65
 			      "pushaw\n\t"
66
+			      "movw %%sp, %%bp\n\t"
67
+			      "andb $~0x01, 22(%%bp)\n\t" /* Clear return CF */
66 68
 			      "leaw e820map(%%bx), %%si\n\t"
67 69
 			      "cs rep movsb\n\t"
68 70
 			      "popaw\n\t"
@@ -73,8 +75,7 @@ void fake_e820 ( void ) {
73 75
 			      "xorl %%ebx,%%ebx\n\t"
74 76
 			      "\n1:\n\t"
75 77
 			      "popfw\n\t"
76
-			      "clc\n\t"
77
-			      "lret $2\n\t"
78
+			      "iret\n\t"
78 79
 			      "\n99:\n\t"
79 80
 			      "popfw\n\t"
80 81
 			      "ljmp *%%cs:real_int15_vector\n\t" )

+ 5
- 2
src/arch/i386/interface/pxe/pxe_entry.S Zobrazit soubor

@@ -199,9 +199,12 @@ pxe_int_1a:
199 199
 	shll	$4, %edx
200 200
 	addl	$pxenv, %edx
201 201
 	movw	$0x564e, %ax
202
+	pushw	%bp
203
+	movw	%sp, %bp
204
+	andb	$~0x01, 8(%bp)	/* Clear CF on return */
205
+	popw	%bp
202 206
 	popfw
203
-	clc
204
-	lret	$2
207
+	iret
205 208
 1:	/* INT 1A,other - pass through */
206 209
 	popfw
207 210
 	ljmp	*%cs:pxe_int_1a_vector

Načítá se…
Zrušit
Uložit