[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