lkml.org 
[lkml]   [2015]   [Jul]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH 4/7] x86/vm86: Move vm86 fields out of thread_struct
Date
Allocate a separate structure for the vm86 fields.

Signed-off-by: Brian Gerst <brgerst@gmail.com>
---
arch/x86/include/asm/processor.h | 9 ++------
arch/x86/include/asm/vm86.h | 8 +++++++
arch/x86/kernel/process.c | 7 ++++++
arch/x86/kernel/vm86_32.c | 47 ++++++++++++++++++++++++----------------
arch/x86/mm/fault.c | 4 ++--
5 files changed, 47 insertions(+), 28 deletions(-)

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 35ad554..d636fb8 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -403,13 +403,9 @@ struct thread_struct {
unsigned long cr2;
unsigned long trap_nr;
unsigned long error_code;
-#ifdef CONFIG_X86_32
+#ifdef CONFIG_VM86
/* Virtual 86 mode info */
- struct vm86plus_struct __user *vm86_info;
- unsigned long screen_bitmap;
- unsigned long v86flags;
- unsigned long v86mask;
- unsigned long saved_sp0;
+ struct kernel_vm86_info *vm86;
#endif
/* IO permissions: */
unsigned long *io_bitmap_ptr;
@@ -714,7 +710,6 @@ static inline void spin_lock_prefetch(const void *x)

#define INIT_THREAD { \
.sp0 = TOP_OF_INIT_STACK, \
- .vm86_info = NULL, \
.sysenter_cs = __KERNEL_CS, \
.io_bitmap_ptr = NULL, \
}
diff --git a/arch/x86/include/asm/vm86.h b/arch/x86/include/asm/vm86.h
index 1d8de3f..a02967d 100644
--- a/arch/x86/include/asm/vm86.h
+++ b/arch/x86/include/asm/vm86.h
@@ -58,6 +58,14 @@ struct kernel_vm86_struct {
*/
};

+struct kernel_vm86_info {
+ struct vm86plus_struct __user *vm86_info;
+ unsigned long screen_bitmap;
+ unsigned long v86flags;
+ unsigned long v86mask;
+ unsigned long saved_sp0;
+};
+
#ifdef CONFIG_VM86

void handle_vm86_fault(struct kernel_vm86_regs *, long);
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 9cad694..5dcd037 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -110,6 +110,13 @@ void exit_thread(void)
kfree(bp);
}

+#ifdef CONFIG_VM86
+ if (t->vm86) {
+ kfree(t->vm86);
+ t->vm86 = NULL;
+ }
+#endif
+
fpu__drop(fpu);
}

diff --git a/arch/x86/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c
index e6c2b47..dce0a1c 100644
--- a/arch/x86/kernel/vm86_32.c
+++ b/arch/x86/kernel/vm86_32.c
@@ -44,6 +44,7 @@
#include <linux/ptrace.h>
#include <linux/audit.h>
#include <linux/stddef.h>
+#include <linux/slab.h>

#include <asm/uaccess.h>
#include <asm/io.h>
@@ -81,8 +82,8 @@
/*
* virtual flags (16 and 32-bit versions)
*/
-#define VFLAGS (*(unsigned short *)&(current->thread.v86flags))
-#define VEFLAGS (current->thread.v86flags)
+#define VFLAGS (*(unsigned short *)&(current->thread.vm86->v86flags))
+#define VEFLAGS (current->thread.vm86->v86flags)

#define set_flags(X, new, mask) \
((X) = ((X) & ~(mask)) | ((new) & (mask)))
@@ -96,6 +97,7 @@ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs)
struct pt_regs *ret;
struct task_struct *tsk = current;
struct vm86plus_struct __user *user;
+ struct kernel_vm86_info *vm86 = current->thread.vm86;
long err = 0;

/*
@@ -105,12 +107,12 @@ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs)
*/
local_irq_enable();

- if (!tsk->thread.vm86_info) {
+ if (!vm86 || !vm86->vm86_info) {
pr_alert("no vm86_info: BAD\n");
do_exit(SIGSEGV);
}
- set_flags(regs->pt.flags, VEFLAGS, X86_EFLAGS_VIF | tsk->thread.v86mask);
- user = tsk->thread.vm86_info;
+ set_flags(regs->pt.flags, VEFLAGS, X86_EFLAGS_VIF | vm86->v86mask);
+ user = vm86->vm86_info;

if (!access_ok(VERIFY_WRITE, user, VMPI.is_vm86pus ?
sizeof(struct vm86plus_struct) :
@@ -137,7 +139,7 @@ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs)
put_user_ex(regs->fs, &user->regs.fs);
put_user_ex(regs->gs, &user->regs.gs);

- put_user_ex(tsk->thread.screen_bitmap, &user->screen_bitmap);
+ put_user_ex(vm86->screen_bitmap, &user->screen_bitmap);
} put_user_catch(err);
if (err) {
pr_alert("could not access userspace vm86_info\n");
@@ -145,10 +147,10 @@ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs)
}

tss = &per_cpu(cpu_tss, get_cpu());
- tsk->thread.sp0 = tsk->thread.saved_sp0;
+ tsk->thread.sp0 = vm86->saved_sp0;
tsk->thread.sysenter_cs = __KERNEL_CS;
load_sp0(tss, &tsk->thread);
- tsk->thread.saved_sp0 = 0;
+ vm86->saved_sp0 = 0;
put_cpu();

ret = KVM86->regs32;
@@ -242,9 +244,16 @@ static long do_sys_vm86(struct vm86plus_struct __user *v86, bool plus,
{
struct tss_struct *tss;
struct task_struct *tsk = current;
+ struct kernel_vm86_info *vm86 = tsk->thread.vm86;
unsigned long err = 0;

- if (tsk->thread.saved_sp0)
+ if (!vm86)
+ {
+ if (!(vm86 = kzalloc(sizeof(*vm86), GFP_KERNEL)))
+ return -ENOMEM;
+ tsk->thread.vm86 = vm86;
+ }
+ if (vm86->saved_sp0)
return -EPERM;

if (!access_ok(VERIFY_READ, v86, plus ?
@@ -295,7 +304,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *v86, bool plus,
}

info->regs32 = current_pt_regs();
- tsk->thread.vm86_info = v86;
+ vm86->vm86_info = v86;

/*
* The flags register is also special: we cannot trust that the user
@@ -311,16 +320,16 @@ static long do_sys_vm86(struct vm86plus_struct __user *v86, bool plus,

switch (info->cpu_type) {
case CPU_286:
- tsk->thread.v86mask = 0;
+ vm86->v86mask = 0;
break;
case CPU_386:
- tsk->thread.v86mask = X86_EFLAGS_NT | X86_EFLAGS_IOPL;
+ vm86->v86mask = X86_EFLAGS_NT | X86_EFLAGS_IOPL;
break;
case CPU_486:
- tsk->thread.v86mask = X86_EFLAGS_AC | X86_EFLAGS_NT | X86_EFLAGS_IOPL;
+ vm86->v86mask = X86_EFLAGS_AC | X86_EFLAGS_NT | X86_EFLAGS_IOPL;
break;
default:
- tsk->thread.v86mask = X86_EFLAGS_ID | X86_EFLAGS_AC | X86_EFLAGS_NT | X86_EFLAGS_IOPL;
+ vm86->v86mask = X86_EFLAGS_ID | X86_EFLAGS_AC | X86_EFLAGS_NT | X86_EFLAGS_IOPL;
break;
}

@@ -328,7 +337,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *v86, bool plus,
* Save old state, set default return value (%ax) to 0 (VM86_SIGNAL)
*/
info->regs32->ax = VM86_SIGNAL;
- tsk->thread.saved_sp0 = tsk->thread.sp0;
+ vm86->saved_sp0 = tsk->thread.sp0;
lazy_save_gs(info->regs32->gs);

tss = &per_cpu(cpu_tss, get_cpu());
@@ -338,7 +347,7 @@ static long do_sys_vm86(struct vm86plus_struct __user *v86, bool plus,
load_sp0(tss, &tsk->thread);
put_cpu();

- tsk->thread.screen_bitmap = info->screen_bitmap;
+ vm86->screen_bitmap = info->screen_bitmap;
if (info->flags & VM86_SCREEN_BITMAP)
mark_screen_rdonly(tsk->mm);

@@ -408,7 +417,7 @@ static inline void clear_AC(struct kernel_vm86_regs *regs)

static inline void set_vflags_long(unsigned long flags, struct kernel_vm86_regs *regs)
{
- set_flags(VEFLAGS, flags, current->thread.v86mask);
+ set_flags(VEFLAGS, flags, current->thread.vm86->v86mask);
set_flags(regs->pt.flags, flags, SAFE_MASK);
if (flags & X86_EFLAGS_IF)
set_IF(regs);
@@ -418,7 +427,7 @@ static inline void set_vflags_long(unsigned long flags, struct kernel_vm86_regs

static inline void set_vflags_short(unsigned short flags, struct kernel_vm86_regs *regs)
{
- set_flags(VFLAGS, flags, current->thread.v86mask);
+ set_flags(VFLAGS, flags, current->thread.vm86->v86mask);
set_flags(regs->pt.flags, flags, SAFE_MASK);
if (flags & X86_EFLAGS_IF)
set_IF(regs);
@@ -433,7 +442,7 @@ static inline unsigned long get_vflags(struct kernel_vm86_regs *regs)
if (VEFLAGS & X86_EFLAGS_VIF)
flags |= X86_EFLAGS_IF;
flags |= X86_EFLAGS_IOPL;
- return flags | (VEFLAGS & current->thread.v86mask);
+ return flags | (VEFLAGS & current->thread.vm86->v86mask);
}

static inline int is_revectored(int nr, struct revectored_struct *bitmap)
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 81dcebf..5196ac4 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -315,12 +315,12 @@ check_v8086_mode(struct pt_regs *regs, unsigned long address,
{
unsigned long bit;

- if (!v8086_mode(regs))
+ if (!v8086_mode(regs) || !tsk->thread.vm86)
return;

bit = (address - 0xA0000) >> PAGE_SHIFT;
if (bit < 32)
- tsk->thread.screen_bitmap |= 1 << bit;
+ tsk->thread.vm86->screen_bitmap |= 1 << bit;
}

static bool low_pfn(unsigned long pfn)
--
2.4.3


\
 
 \ /
  Last update: 2015-07-20 03:21    [W:0.097 / U:0.096 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site