/root/src/xen/xen/arch/x86/pv/emulate.c
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * arch/x86/pv/emulate.c |
3 | | * |
4 | | * Common PV emulation code |
5 | | * |
6 | | * Modifications to Linux original are copyright (c) 2002-2004, K A Fraser |
7 | | * |
8 | | * This program is free software; you can redistribute it and/or modify |
9 | | * it under the terms of the GNU General Public License as published by |
10 | | * the Free Software Foundation; either version 2 of the License, or |
11 | | * (at your option) any later version. |
12 | | * |
13 | | * This program is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU General Public License |
19 | | * along with this program; If not, see <http://www.gnu.org/licenses/>. |
20 | | */ |
21 | | |
22 | | #include <xen/guest_access.h> |
23 | | |
24 | | #include <asm/debugreg.h> |
25 | | |
26 | | #include "emulate.h" |
27 | | |
28 | | int pv_emul_read_descriptor(unsigned int sel, const struct vcpu *v, |
29 | | unsigned long *base, unsigned long *limit, |
30 | | unsigned int *ar, bool insn_fetch) |
31 | 0 | { |
32 | 0 | struct desc_struct desc; |
33 | 0 |
|
34 | 0 | if ( sel < 4) |
35 | 0 | desc.b = desc.a = 0; |
36 | 0 | else if ( __get_user(desc, |
37 | 0 | (const struct desc_struct *)(!(sel & 4) |
38 | 0 | ? GDT_VIRT_START(v) |
39 | 0 | : LDT_VIRT_START(v)) |
40 | 0 | + (sel >> 3)) ) |
41 | 0 | return 0; |
42 | 0 | if ( !insn_fetch ) |
43 | 0 | desc.b &= ~_SEGMENT_L; |
44 | 0 |
|
45 | 0 | *ar = desc.b & 0x00f0ff00; |
46 | 0 | if ( !(desc.b & _SEGMENT_L) ) |
47 | 0 | { |
48 | 0 | *base = ((desc.a >> 16) + ((desc.b & 0xff) << 16) + |
49 | 0 | (desc.b & 0xff000000)); |
50 | 0 | *limit = (desc.a & 0xffff) | (desc.b & 0x000f0000); |
51 | 0 | if ( desc.b & _SEGMENT_G ) |
52 | 0 | *limit = ((*limit + 1) << 12) - 1; |
53 | 0 | #ifndef NDEBUG |
54 | 0 | if ( sel > 3 ) |
55 | 0 | { |
56 | 0 | unsigned int a, l; |
57 | 0 | unsigned char valid; |
58 | 0 |
|
59 | 0 | asm volatile ( |
60 | 0 | "larl %2,%0 ; setz %1" |
61 | 0 | : "=r" (a), "=qm" (valid) : "rm" (sel)); |
62 | 0 | BUG_ON(valid && ((a & 0x00f0ff00) != *ar)); |
63 | 0 | asm volatile ( |
64 | 0 | "lsll %2,%0 ; setz %1" |
65 | 0 | : "=r" (l), "=qm" (valid) : "rm" (sel)); |
66 | 0 | BUG_ON(valid && (l != *limit)); |
67 | 0 | } |
68 | 0 | #endif |
69 | 0 | } |
70 | 0 | else |
71 | 0 | { |
72 | 0 | *base = 0UL; |
73 | 0 | *limit = ~0UL; |
74 | 0 | } |
75 | 0 |
|
76 | 0 | return 1; |
77 | 0 | } |
78 | | |
79 | | void pv_emul_instruction_done(struct cpu_user_regs *regs, unsigned long rip) |
80 | 0 | { |
81 | 0 | regs->rip = rip; |
82 | 0 | regs->eflags &= ~X86_EFLAGS_RF; |
83 | 0 | if ( regs->eflags & X86_EFLAGS_TF ) |
84 | 0 | { |
85 | 0 | current->arch.debugreg[6] |= DR_STEP | DR_STATUS_RESERVED_ONE; |
86 | 0 | pv_inject_hw_exception(TRAP_debug, X86_EVENT_NO_EC); |
87 | 0 | } |
88 | 0 | } |
89 | | |
90 | | /* |
91 | | * Local variables: |
92 | | * mode: C |
93 | | * c-file-style: "BSD" |
94 | | * c-basic-offset: 4 |
95 | | * tab-width: 4 |
96 | | * indent-tabs-mode: nil |
97 | | * End: |
98 | | */ |