aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2010-06-21 10:03:03 -0700
committerH. Peter Anvin <hpa@zytor.com>2010-06-21 10:03:03 -0700
commit4e7d836b8cdc0e785ac6e0a78b258c4e193d2222 (patch)
treec0acaa9605394ce10dbdbea7e7f2be44d607ec07
parentee367a7d8215eea0b59a4f672b8fcfb5544c5f5a (diff)
downloadsyslinux-4e7d836b8cdc0e785ac6e0a78b258c4e193d2222.tar.gz
syslinux-4e7d836b8cdc0e785ac6e0a78b258c4e193d2222.tar.xz
syslinux-4e7d836b8cdc0e785ac6e0a78b258c4e193d2222.zip
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@zytor.com>
-rw-r--r--core/call16.c18
-rw-r--r--core/callback.inc2
2 files changed, 17 insertions, 3 deletions
diff --git a/core/call16.c b/core/call16.c
index 86d70461..095f814f 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 a33b5825..6a351327 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