[syslinux:master] core: Preserve IF through call16()

syslinux-bot for H. Peter Anvin hpa at zytor.com
Mon Jun 21 10:06:25 PDT 2010


Commit-ID:  4e7d836b8cdc0e785ac6e0a78b258c4e193d2222
Gitweb:     http://syslinux.zytor.com/commit/4e7d836b8cdc0e785ac6e0a78b258c4e193d2222
Author:     H. Peter Anvin <hpa at zytor.com>
AuthorDate: Mon, 21 Jun 2010 10:03:03 -0700
Committer:  H. Peter Anvin <hpa at zytor.com>
CommitDate: Mon, 21 Jun 2010 10:03:03 -0700

core: Preserve IF through call16()

An intcall should always be invoked with interrupts off, but that is
not necessarily the case for a near or far call; in fact it is quite
the exception.  As such, do not filter IF in our register image, and
for our own internal call16() interface, propagate the protected-mode
IF value into real mode, just as we do for the pm_call interface.

Signed-off-by: H. Peter Anvin <hpa at zytor.com>


---
 core/call16.c     |   18 ++++++++++++++++--
 core/callback.inc |    2 +-
 2 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/core/call16.c b/core/call16.c
index 86d7046..095f814 100644
--- a/core/call16.c
+++ b/core/call16.c
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------- *
  *
- *   Copyright 2009 Intel Corporation; author: H. Peter Anvin
+ *   Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
  *
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -17,11 +17,25 @@
  */
 
 #include <stddef.h>
+#include <stdio.h>
 #include "core.h"
 
 const com32sys_t zero_regs;	/* Common all-zero register set */
 
+static inline uint32_t eflags(void)
+{
+    uint32_t v;
+
+    asm volatile("pushfl ; popl %0" : "=rm" (v));
+    return v;
+}
+
 void call16(void (*func)(void), const com32sys_t *ireg, com32sys_t *oreg)
 {
-    core_farcall((size_t)func, ireg, oreg);
+    com32sys_t xreg = *ireg;
+
+    /* Enable interrupts if and only if they are enabled in the caller */
+    xreg.eflags.l = (xreg.eflags.l & ~EFLAGS_IF) | (eflags() & EFLAGS_IF);
+
+    core_farcall((size_t)func, &xreg, oreg);
 }
diff --git a/core/callback.inc b/core/callback.inc
index a33b582..6a35132 100644
--- a/core/callback.inc
+++ b/core/callback.inc
@@ -74,7 +74,7 @@ core_syscall:
 		mov eax,.rm_return	; Return seg:offs
 		stosd			; Save in stack frame
 		mov eax,[edi-12]	; Return flags
-		and eax,0x200cd7	; Mask (potentially) unsafe flags
+		and eax,0x200ed7	; Mask (potentially) unsafe flags
 		mov [edi-12],eax	; Primary flags entry
 		stosw			; Return flags
 



More information about the Syslinux-commits mailing list