direct-io.hg
changeset 3569:cd26f113b1b1
bitkeeper revision 1.1159.231.12 (41f97ef6r1c2TDcgR-o8jFV1IWm5dA)
Lean decoder for MMIO instructions.
Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
Signed-off-by: Chengyuan Li <chengyuan.li@intel.com>
Signed-off-by: ian.pratt@cl.cam.ac.uk
Lean decoder for MMIO instructions.
Signed-off-by: Jun Nakajima <jun.nakajima@intel.com>
Signed-off-by: Chengyuan Li <chengyuan.li@intel.com>
Signed-off-by: ian.pratt@cl.cam.ac.uk
author | iap10@labyrinth.cl.cam.ac.uk |
---|---|
date | Thu Jan 27 23:53:26 2005 +0000 (2005-01-27) |
parents | 002034af24e6 |
children | bc0fbb38cb25 20c37da2d56b |
files | .rootkeys xen/arch/x86/vmx.c xen/arch/x86/vmx_io.c xen/arch/x86/vmx_platform.c xen/include/asm-x86/shadow.h xen/include/asm-x86/vmx_platform.h xen/include/asm-x86/vmx_vmcs.h |
line diff
1.1 --- a/.rootkeys Thu Jan 27 23:49:46 2005 +0000 1.2 +++ b/.rootkeys Thu Jan 27 23:53:26 2005 +0000 1.3 @@ -891,6 +891,7 @@ 3ddb79bccYVzXZJyVaxuv5T42Z1Fsw xen/arch/ 1.4 3ddb79bcOftONV9h4QCxXOfiT0h91w xen/arch/x86/traps.c 1.5 41c0c411tD3C7TpfDMiFTf7BaNd_Dg xen/arch/x86/vmx.c 1.6 41c0c411ODt8uEmV-yUxpQLpqimE5Q xen/arch/x86/vmx_io.c 1.7 +41f97ef5139vN42cOYHfX_Ac8WOOjA xen/arch/x86/vmx_platform.c 1.8 41c0c4128URE0dxcO15JME_MuKBPfg xen/arch/x86/vmx_vmcs.c 1.9 419cbedeQDg8IrO3izo3o5rQNlo0kQ xen/arch/x86/x86_32/asm-offsets.c 1.10 3e32af9aRnYGl4GMOaDKp7JdfhOGhg xen/arch/x86/x86_32/domain_page.c
2.1 --- a/xen/arch/x86/vmx.c Thu Jan 27 23:49:46 2005 +0000 2.2 +++ b/xen/arch/x86/vmx.c Thu Jan 27 23:53:26 2005 +0000 2.3 @@ -107,7 +107,7 @@ static int vmx_do_page_fault(unsigned lo 2.4 { 2.5 unsigned long eip, pfn; 2.6 unsigned int index; 2.7 - unsigned long gpde = 0; 2.8 + unsigned long gpde = 0, gpte, gpa; 2.9 int result; 2.10 struct exec_domain *ed = current; 2.11 struct mm_struct *m = &ed->mm; 2.12 @@ -137,6 +137,15 @@ static int vmx_do_page_fault(unsigned lo 2.13 m->guest_pl2e_cache[index] = 2.14 mk_l2_pgentry((pfn << PAGE_SHIFT) | __PAGE_HYPERVISOR); 2.15 } 2.16 + 2.17 + if (unlikely(__get_user(gpte, (unsigned long *) 2.18 + &linear_pg_table[va >> PAGE_SHIFT]))) 2.19 + return 0; 2.20 + 2.21 + gpa = (gpte & PAGE_MASK) | (va & (PAGE_SIZE - 1)); 2.22 + 2.23 + if (mmio_space(gpa)) 2.24 + handle_mmio(va, gpte, gpa); 2.25 2.26 if ((result = shadow_fault(va, error_code))) 2.27 return result; 2.28 @@ -283,7 +292,7 @@ static inline void guest_pl2e_cache_inva 2.29 memset(m->guest_pl2e_cache, 0, PAGE_SIZE); 2.30 } 2.31 2.32 -static inline unsigned long gva_to_gpa(unsigned long gva) 2.33 +inline unsigned long gva_to_gpa(unsigned long gva) 2.34 { 2.35 unsigned long gpde, gpte, pfn, index; 2.36 struct exec_domain *d = current; 2.37 @@ -784,6 +793,7 @@ asmlinkage void vmx_vmexit_handler(struc 2.38 __vmread(VM_EXIT_INTR_ERROR_CODE, &error_code); 2.39 VMX_DBG_LOG(DBG_LEVEL_VMMU, 2.40 "eax=%x, ebx=%x, ecx=%x, edx=%x, esi=%x, edi=%x\n", regs.eax, regs.ebx, regs.ecx, regs.edx, regs.esi, regs.edi); 2.41 + d->thread.arch_vmx.vmx_platform.mpci.inst_decoder_regs = ®s; 2.42 2.43 if (!(error = vmx_do_page_fault(va, error_code))) { 2.44 /*
3.1 --- a/xen/arch/x86/vmx_io.c Thu Jan 27 23:49:46 2005 +0000 3.2 +++ b/xen/arch/x86/vmx_io.c Thu Jan 27 23:53:26 2005 +0000 3.3 @@ -29,8 +29,143 @@ 3.4 #include <asm/vmx_vmcs.h> 3.5 #include <xen/event.h> 3.6 #include <public/io/ioreq.h> 3.7 +#include <asm/vmx_platform.h> 3.8 3.9 extern long do_block(); 3.10 + 3.11 +#if defined (__i386__) 3.12 +static void load_xen_regs(struct xen_regs *regs) 3.13 +{ 3.14 + /* 3.15 + * Write the guest register value into VMCS 3.16 + */ 3.17 + __vmwrite(GUEST_SS_SELECTOR, regs->ss); 3.18 + __vmwrite(GUEST_ESP, regs->esp); 3.19 + __vmwrite(GUEST_EFLAGS, regs->eflags); 3.20 + __vmwrite(GUEST_CS_SELECTOR, regs->cs); 3.21 + __vmwrite(GUEST_EIP, regs->eip); 3.22 +} 3.23 + 3.24 +static void set_reg_value (int size, int index, int seg, struct xen_regs *regs, long value) 3.25 +{ 3.26 + switch (size) { 3.27 + case BYTE: 3.28 + switch (index) { 3.29 + case 0: 3.30 + regs->eax &= 0xFFFFFF00; 3.31 + regs->eax |= (value & 0xFF); 3.32 + break; 3.33 + case 1: 3.34 + regs->ecx &= 0xFFFFFF00; 3.35 + regs->ecx |= (value & 0xFF); 3.36 + break; 3.37 + case 2: 3.38 + regs->edx &= 0xFFFFFF00; 3.39 + regs->edx |= (value & 0xFF); 3.40 + break; 3.41 + case 3: 3.42 + regs->ebx &= 0xFFFFFF00; 3.43 + regs->ebx |= (value & 0xFF); 3.44 + break; 3.45 + case 4: 3.46 + regs->eax &= 0xFFFF00FF; 3.47 + regs->eax |= ((value & 0xFF) << 8); 3.48 + break; 3.49 + case 5: 3.50 + regs->ecx &= 0xFFFF00FF; 3.51 + regs->ecx |= ((value & 0xFF) << 8); 3.52 + break; 3.53 + case 6: 3.54 + regs->edx &= 0xFFFF00FF; 3.55 + regs->edx |= ((value & 0xFF) << 8); 3.56 + break; 3.57 + case 7: 3.58 + regs->ebx &= 0xFFFF00FF; 3.59 + regs->ebx |= ((value & 0xFF) << 8); 3.60 + break; 3.61 + default: 3.62 + printk("size:%x, index:%x are invalid!\n", size, index); 3.63 + break; 3.64 + 3.65 + } 3.66 + break; 3.67 + case WORD: 3.68 + switch (index) { 3.69 + case 0: 3.70 + regs->eax &= 0xFFFF0000; 3.71 + regs->eax |= (value & 0xFFFF); 3.72 + break; 3.73 + case 1: 3.74 + regs->ecx &= 0xFFFF0000; 3.75 + regs->ecx |= (value & 0xFFFF); 3.76 + break; 3.77 + case 2: 3.78 + regs->edx &= 0xFFFF0000; 3.79 + regs->edx |= (value & 0xFFFF); 3.80 + break; 3.81 + case 3: 3.82 + regs->ebx &= 0xFFFF0000; 3.83 + regs->ebx |= (value & 0xFFFF); 3.84 + break; 3.85 + case 4: 3.86 + regs->esp &= 0xFFFF0000; 3.87 + regs->esp |= (value & 0xFFFF); 3.88 + break; 3.89 + 3.90 + case 5: 3.91 + regs->ebp &= 0xFFFF0000; 3.92 + regs->ebp |= (value & 0xFFFF); 3.93 + break; 3.94 + case 6: 3.95 + regs->esi &= 0xFFFF0000; 3.96 + regs->esi |= (value & 0xFFFF); 3.97 + break; 3.98 + case 7: 3.99 + regs->edi &= 0xFFFF0000; 3.100 + regs->edi |= (value & 0xFFFF); 3.101 + break; 3.102 + default: 3.103 + printk("size:%x, index:%x are invalid!\n", size, index); 3.104 + break; 3.105 + } 3.106 + break; 3.107 + case LONG: 3.108 + switch (index) { 3.109 + case 0: 3.110 + regs->eax = value; 3.111 + break; 3.112 + case 1: 3.113 + regs->ecx = value; 3.114 + break; 3.115 + case 2: 3.116 + regs->edx = value; 3.117 + break; 3.118 + case 3: 3.119 + regs->ebx = value; 3.120 + break; 3.121 + case 4: 3.122 + regs->esp = value; 3.123 + break; 3.124 + case 5: 3.125 + regs->ebp = value; 3.126 + break; 3.127 + case 6: 3.128 + regs->esi = value; 3.129 + break; 3.130 + case 7: 3.131 + regs->edi = value; 3.132 + break; 3.133 + default: 3.134 + printk("size:%x, index:%x are invalid!\n", size, index); 3.135 + break; 3.136 + } 3.137 + break; 3.138 + default: 3.139 + printk("size:%x, index:%x are invalid!\n", size, index); 3.140 + break; 3.141 + } 3.142 +} 3.143 +#endif 3.144 3.145 void vmx_io_assist(struct exec_domain *ed) 3.146 { 3.147 @@ -40,6 +175,11 @@ void vmx_io_assist(struct exec_domain *e 3.148 execution_context_t *ec = get_execution_context(); 3.149 unsigned long old_eax; 3.150 int sign; 3.151 + struct mi_per_cpu_info *mpci_p; 3.152 + struct xen_regs *inst_decoder_regs; 3.153 + 3.154 + mpci_p = &ed->thread.arch_vmx.vmx_platform.mpci; 3.155 + inst_decoder_regs = mpci_p->inst_decoder_regs; 3.156 3.157 /* clear the pending event */ 3.158 ed->vcpu_info->evtchn_upcall_pending = 0; 3.159 @@ -76,7 +216,19 @@ void vmx_io_assist(struct exec_domain *e 3.160 if (p->dir == IOREQ_WRITE) { 3.161 return; 3.162 } 3.163 + int size = -1, index = -1; 3.164 + 3.165 + size = operand_size(ed->thread.arch_vmx.vmx_platform.mpci.mmio_target); 3.166 + index = operand_index(ed->thread.arch_vmx.vmx_platform.mpci.mmio_target); 3.167 + 3.168 + if (ed->thread.arch_vmx.vmx_platform.mpci.mmio_target & WZEROEXTEND) { 3.169 + p->u.data = p->u.data & 0xffff; 3.170 + } 3.171 + set_reg_value(size, index, 0, (struct xen_regs *)ec, p->u.data); 3.172 + 3.173 } 3.174 + load_xen_regs((struct xen_regs *)ec); 3.175 + return; 3.176 } 3.177 3.178 if (p->dir == IOREQ_WRITE) {
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/xen/arch/x86/vmx_platform.c Thu Jan 27 23:53:26 2005 +0000 4.3 @@ -0,0 +1,554 @@ 4.4 +/* 4.5 + * vmx_platform.c: handling x86 platform related MMIO instructions 4.6 + * Copyright (c) 2004, Intel Corporation. 4.7 + * 4.8 + * This program is free software; you can redistribute it and/or modify it 4.9 + * under the terms and conditions of the GNU General Public License, 4.10 + * version 2, as published by the Free Software Foundation. 4.11 + * 4.12 + * This program is distributed in the hope it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 4.15 + * more details. 4.16 + * 4.17 + * You should have received a copy of the GNU General Public License along with 4.18 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 4.19 + * Place - Suite 330, Boston, MA 02111-1307 USA. 4.20 + * 4.21 + */ 4.22 + 4.23 +#include <xen/config.h> 4.24 +#include <xen/types.h> 4.25 +#include <xen/mm.h> 4.26 +#include <asm/shadow.h> 4.27 +#include <asm/domain_page.h> 4.28 +#include <asm/page.h> 4.29 +#include <xen/event.h> 4.30 +#include <xen/trace.h> 4.31 +#include <asm/vmx.h> 4.32 +#include <asm/vmx_platform.h> 4.33 +#include <public/io/ioreq.h> 4.34 + 4.35 +#include <xen/lib.h> 4.36 +#include <xen/sched.h> 4.37 +#include <asm/current.h> 4.38 + 4.39 +#define DECODE_success 1 4.40 +#define DECODE_failure 0 4.41 + 4.42 +#if defined (__x86_64__) 4.43 +static void store_xen_regs(struct xen_regs *regs) 4.44 +{ 4.45 + 4.46 +} 4.47 + 4.48 +static long get_reg_value(int size, int index, int seg, struct xen_regs *regs) 4.49 +{ 4.50 + return 0; 4.51 +} 4.52 +#elif defined (__i386__) 4.53 +static void store_xen_regs(struct xen_regs *regs) 4.54 +{ 4.55 + __vmread(GUEST_SS_SELECTOR, ®s->ss); 4.56 + __vmread(GUEST_ESP, ®s->esp); 4.57 + __vmread(GUEST_EFLAGS, ®s->eflags); 4.58 + __vmread(GUEST_CS_SELECTOR, ®s->cs); 4.59 + __vmread(GUEST_EIP, ®s->eip); 4.60 +} 4.61 + 4.62 +static long get_reg_value(int size, int index, int seg, struct xen_regs *regs) 4.63 +{ 4.64 + /* 4.65 + * Reference the db_reg[] table 4.66 + */ 4.67 + switch (size) { 4.68 + case BYTE: 4.69 + switch (index) { 4.70 + case 0: //%al 4.71 + return (char)(regs->eax & 0xFF); 4.72 + case 1: //%cl 4.73 + return (char)(regs->ecx & 0xFF); 4.74 + case 2: //%dl 4.75 + return (char)(regs->edx & 0xFF); 4.76 + case 3: //%bl 4.77 + return (char)(regs->ebx & 0xFF); 4.78 + case 4: //%ah 4.79 + return (char)((regs->eax & 0xFF00) >> 8); 4.80 + case 5: //%ch 4.81 + return (char)((regs->ecx & 0xFF00) >> 8); 4.82 + case 6: //%dh 4.83 + return (char)((regs->edx & 0xFF00) >> 8); 4.84 + case 7: //%bh 4.85 + return (char)((regs->ebx & 0xFF00) >> 8); 4.86 + default: 4.87 + printk("(get_reg_value)size case 0 error\n"); 4.88 + return -1; 4.89 + } 4.90 + case WORD: 4.91 + switch (index) { 4.92 + case 0: //%ax 4.93 + return (short)(regs->eax & 0xFFFF); 4.94 + case 1: //%cx 4.95 + return (short)(regs->ecx & 0xFFFF); 4.96 + case 2: //%dx 4.97 + return (short)(regs->edx & 0xFFFF); 4.98 + case 3: //%bx 4.99 + return (short)(regs->ebx & 0xFFFF); 4.100 + case 4: //%sp 4.101 + return (short)(regs->esp & 0xFFFF); 4.102 + break; 4.103 + case 5: //%bp 4.104 + return (short)(regs->ebp & 0xFFFF); 4.105 + case 6: //%si 4.106 + return (short)(regs->esi & 0xFFFF); 4.107 + case 7: //%di 4.108 + return (short)(regs->edi & 0xFFFF); 4.109 + default: 4.110 + printk("(get_reg_value)size case 1 error\n"); 4.111 + return -1; 4.112 + } 4.113 + case LONG: 4.114 + switch (index) { 4.115 + case 0: //%eax 4.116 + return regs->eax; 4.117 + case 1: //%ecx 4.118 + return regs->ecx; 4.119 + case 2: //%edx 4.120 + return regs->edx; 4.121 + 4.122 + case 3: //%ebx 4.123 + return regs->ebx; 4.124 + case 4: //%esp 4.125 + return regs->esp; 4.126 + case 5: //%ebp 4.127 + return regs->ebp; 4.128 + case 6: //%esi 4.129 + return regs->esi; 4.130 + case 7: //%edi 4.131 + return regs->edi; 4.132 + default: 4.133 + printk("(get_reg_value)size case 2 error\n"); 4.134 + return -1; 4.135 + } 4.136 + default: 4.137 + printk("(get_reg_value)size case error\n"); 4.138 + return -1; 4.139 + } 4.140 +} 4.141 +#endif 4.142 + 4.143 +static inline unsigned char *check_prefix(unsigned char *inst, struct instruction *thread_inst) 4.144 +{ 4.145 + while (1) { 4.146 + switch (*inst) { 4.147 + case 0xf3: //REPZ 4.148 + case 0xf2: //REPNZ 4.149 + case 0xf0: //LOCK 4.150 + case 0x2e: //CS 4.151 + case 0x36: //SS 4.152 + case 0x3e: //DS 4.153 + case 0x26: //ES 4.154 + case 0x64: //FS 4.155 + case 0x65: //GS 4.156 + break; 4.157 + case 0x66: //32bit->16bit 4.158 + thread_inst->op_size = WORD; 4.159 + break; 4.160 + case 0x67: 4.161 + break; 4.162 + default: 4.163 + return inst; 4.164 + } 4.165 + inst++; 4.166 + } 4.167 +} 4.168 + 4.169 +static inline unsigned long get_immediate(const unsigned char *inst, int op_size) 4.170 +{ 4.171 + int mod, reg, rm; 4.172 + unsigned long val = 0; 4.173 + int i; 4.174 + 4.175 + mod = (*inst >> 6) & 3; 4.176 + reg = (*inst >> 3) & 7; 4.177 + rm = *inst & 7; 4.178 + 4.179 + inst++; //skip ModR/M byte 4.180 + if (mod != 3 && rm == 4) { 4.181 + inst++; //skip SIB byte 4.182 + } 4.183 + 4.184 + switch(mod) { 4.185 + case 0: 4.186 + if (rm == 5) { 4.187 + inst = inst + 4; //disp32, skip 4 bytes 4.188 + } 4.189 + break; 4.190 + case 1: 4.191 + inst++; //disp8, skip 1 byte 4.192 + break; 4.193 + case 2: 4.194 + inst = inst + 4; //disp32, skip 4 bytes 4.195 + } 4.196 + for (i = 0; i < op_size; i++) { 4.197 + val |= (*inst++ & 0xff) << (8 * i); 4.198 + } 4.199 + 4.200 + return val; 4.201 +} 4.202 + 4.203 +static inline int get_index(const unsigned char *inst) 4.204 +{ 4.205 + int mod, reg, rm; 4.206 + 4.207 + mod = (*inst >> 6) & 3; 4.208 + reg = (*inst >> 3) & 7; 4.209 + rm = *inst & 7; 4.210 + 4.211 + //Only one operand in the instruction is register 4.212 + if (mod == 3) { 4.213 + return rm; 4.214 + } else { 4.215 + return reg; 4.216 + } 4.217 + return 0; 4.218 +} 4.219 + 4.220 +static int vmx_decode(const unsigned char *inst, struct instruction *thread_inst) 4.221 +{ 4.222 + int index; 4.223 + 4.224 + switch(*inst) { 4.225 + case 0x88: 4.226 + /* mov r8 to m8 */ 4.227 + thread_inst->op_size = BYTE; 4.228 + index = get_index((inst + 1)); 4.229 + thread_inst->operand[0] = mk_operand(BYTE, index, 0, REGISTER); 4.230 + break; 4.231 + case 0x89: 4.232 + /* mov r32/16 to m32/16 */ 4.233 + index = get_index((inst + 1)); 4.234 + if (thread_inst->op_size == WORD) { 4.235 + thread_inst->operand[0] = mk_operand(WORD, index, 0, REGISTER); 4.236 + } else { 4.237 + thread_inst->op_size = LONG; 4.238 + thread_inst->operand[0] = mk_operand(LONG, index, 0, REGISTER); 4.239 + } 4.240 + break; 4.241 + case 0x8a: 4.242 + /* mov m8 to r8 */ 4.243 + thread_inst->op_size = BYTE; 4.244 + index = get_index((inst + 1)); 4.245 + thread_inst->operand[1] = mk_operand(BYTE, index, 0, REGISTER); 4.246 + break; 4.247 + case 0x8b: 4.248 + /* mov r32/16 to m32/16 */ 4.249 + index = get_index((inst + 1)); 4.250 + if (thread_inst->op_size == WORD) { 4.251 + thread_inst->operand[1] = mk_operand(WORD, index, 0, REGISTER); 4.252 + } else { 4.253 + thread_inst->op_size = LONG; 4.254 + thread_inst->operand[1] = mk_operand(LONG, index, 0, REGISTER); 4.255 + } 4.256 + break; 4.257 + case 0x8c: 4.258 + case 0x8e: 4.259 + printk("%x, This opcode hasn't been handled yet!", *inst); 4.260 + return DECODE_failure; 4.261 + /* Not handle it yet. */ 4.262 + 4.263 + case 0xa0: 4.264 + /* mov byte to al */ 4.265 + thread_inst->op_size = BYTE; 4.266 + thread_inst->operand[1] = mk_operand(BYTE, 0, 0, REGISTER); 4.267 + break; 4.268 + case 0xa1: 4.269 + /* mov word/doubleword to ax/eax */ 4.270 + if (thread_inst->op_size == WORD) { 4.271 + thread_inst->operand[1] = mk_operand(WORD, 0, 0, REGISTER); 4.272 + } else { 4.273 + thread_inst->op_size = LONG; 4.274 + thread_inst->operand[1] = mk_operand(LONG, 0, 0, REGISTER); 4.275 + } 4.276 + break; 4.277 + case 0xa2: 4.278 + /* mov al to (seg:offset) */ 4.279 + thread_inst->op_size = BYTE; 4.280 + thread_inst->operand[0] = mk_operand(BYTE, 0, 0, REGISTER); 4.281 + break; 4.282 + case 0xa3: 4.283 + /* mov ax/eax to (seg:offset) */ 4.284 + if (thread_inst->op_size == WORD) { 4.285 + thread_inst->operand[0] = mk_operand(WORD, 0, 0, REGISTER); 4.286 + } else { 4.287 + thread_inst->op_size = LONG; 4.288 + thread_inst->operand[0] = mk_operand(LONG, 0, 0, REGISTER); 4.289 + } 4.290 + break; 4.291 + case 0xa4: 4.292 + /* movsb */ 4.293 + thread_inst->op_size = BYTE; 4.294 + strcpy(thread_inst->i_name, "movs"); 4.295 + 4.296 + return DECODE_success; 4.297 + case 0xa5: 4.298 + /* movsw/movsl */ 4.299 + if (thread_inst->op_size == WORD) { 4.300 + } else { 4.301 + thread_inst->op_size = LONG; 4.302 + } 4.303 + 4.304 + strcpy(thread_inst->i_name, "movs"); 4.305 + 4.306 + return DECODE_success; 4.307 + 4.308 + case 0xc6: 4.309 + /* mov imm8 to m8 */ 4.310 + thread_inst->op_size = BYTE; 4.311 + thread_inst->operand[0] = mk_operand(BYTE, 0, 0, IMMEDIATE); 4.312 + thread_inst->immediate = get_immediate((inst+1), thread_inst->op_size); 4.313 + break; 4.314 + case 0xc7: 4.315 + /* mov imm16/32 to m16/32 */ 4.316 + if (thread_inst->op_size == WORD) { 4.317 + thread_inst->operand[0] = mk_operand(WORD, 0, 0, IMMEDIATE); 4.318 + } else { 4.319 + thread_inst->op_size = LONG; 4.320 + thread_inst->operand[0] = mk_operand(LONG, 0, 0, IMMEDIATE); 4.321 + } 4.322 + thread_inst->immediate = get_immediate((inst+1), thread_inst->op_size); 4.323 + break; 4.324 + 4.325 + case 0x0f: 4.326 + break; 4.327 + default: 4.328 + printk("%x, This opcode hasn't been handled yet!", *inst); 4.329 + return DECODE_failure; 4.330 + } 4.331 + 4.332 + strcpy(thread_inst->i_name, "mov"); 4.333 + if (*inst != 0x0f) { 4.334 + return DECODE_success; 4.335 + } 4.336 + 4.337 + inst++; 4.338 + switch (*inst) { 4.339 + 4.340 + /* movz */ 4.341 + case 0xb7: 4.342 + index = get_index((inst + 1)); 4.343 + thread_inst->operand[1] = mk_operand(LONG, index, 0, REGISTER); 4.344 + strcpy(thread_inst->i_name, "movzw"); 4.345 + 4.346 + return DECODE_success; 4.347 + default: 4.348 + printk("0f %x, This opcode hasn't been handled yet!", *inst); 4.349 + return DECODE_failure; 4.350 + } 4.351 + 4.352 + /* will never reach here */ 4.353 + return DECODE_failure; 4.354 +} 4.355 + 4.356 +static int inst_copy_from_guest(char *buf, unsigned long guest_eip, int inst_len) 4.357 +{ 4.358 + unsigned long gpte; 4.359 + unsigned long mfn; 4.360 + unsigned long ma; 4.361 + unsigned char * inst_start; 4.362 + 4.363 + if (inst_len > MAX_INST_LEN || inst_len <= 0) { 4.364 + return 0; 4.365 + } 4.366 + 4.367 + if ((guest_eip & PAGE_MASK) == ((guest_eip + inst_len) & PAGE_MASK)) { 4.368 + if ( unlikely(__get_user(gpte, (unsigned long *) 4.369 + &linear_pg_table[guest_eip >> PAGE_SHIFT])) ) 4.370 + { 4.371 + printk("inst_copy_from_guest- EXIT: read gpte faulted" ); 4.372 + return 0; 4.373 + } 4.374 + mfn = phys_to_machine_mapping[gpte >> PAGE_SHIFT]; 4.375 + ma = (mfn << PAGE_SHIFT) | (guest_eip & (PAGE_SIZE - 1)); 4.376 + inst_start = (unsigned char *)map_domain_mem(ma); 4.377 + 4.378 + strncpy(buf, inst_start, inst_len); 4.379 + unmap_domain_mem(inst_start); 4.380 + } else { 4.381 + // Todo: In two page frames 4.382 + } 4.383 + 4.384 + return inst_len; 4.385 +} 4.386 + 4.387 +static void init_instruction(struct instruction *mmio_inst) 4.388 +{ 4.389 + memset(mmio_inst->i_name, '0', I_NAME_LEN); 4.390 + mmio_inst->op_size = 0; 4.391 + mmio_inst->offset = 0; 4.392 + mmio_inst->immediate = 0; 4.393 + mmio_inst->seg_sel = 0; 4.394 + mmio_inst->op_num = 0; 4.395 + 4.396 + mmio_inst->operand[0] = 0; 4.397 + mmio_inst->operand[1] = 0; 4.398 + mmio_inst->operand[2] = 0; 4.399 + 4.400 + mmio_inst->flags = 0; 4.401 +} 4.402 + 4.403 +static int read_from_mmio(struct instruction *inst_p) 4.404 +{ 4.405 + // Only for mov instruction now!!! 4.406 + if (inst_p->operand[1] & REGISTER) 4.407 + return 1; 4.408 + 4.409 + return 0; 4.410 +} 4.411 + 4.412 +// dir: 1 read from mmio 4.413 +// 0 write to mmio 4.414 +static void send_mmio_req(unsigned long gpa, 4.415 + struct instruction *inst_p, long value, int dir, int pvalid) 4.416 +{ 4.417 + struct exec_domain *d = current; 4.418 + vcpu_iodata_t *vio; 4.419 + ioreq_t *p; 4.420 + struct mi_per_cpu_info *mpci_p; 4.421 + struct xen_regs *inst_decoder_regs; 4.422 + extern inline unsigned long gva_to_gpa(unsigned long gva); 4.423 + extern long evtchn_send(int lport); 4.424 + extern long do_block(void); 4.425 + 4.426 + mpci_p = ¤t->thread.arch_vmx.vmx_platform.mpci; 4.427 + inst_decoder_regs = mpci_p->inst_decoder_regs; 4.428 + vio = (vcpu_iodata_t *) d->thread.arch_vmx.vmx_platform.shared_page_va; 4.429 + 4.430 + if (vio == NULL) { 4.431 + printk("bad shared page\n"); 4.432 + domain_crash(); 4.433 + } 4.434 + p = &vio->vp_ioreq; 4.435 + 4.436 + set_bit(ARCH_VMX_IO_WAIT, &d->thread.arch_vmx.flags); 4.437 + p->dir = dir; 4.438 + p->pdata_valid = pvalid; 4.439 + p->count = 1; 4.440 + 4.441 + p->port_mm = 1; 4.442 + p->size = inst_p->op_size; 4.443 + p->addr = gpa; 4.444 + p->u.data = value; 4.445 + 4.446 + // p->state = STATE_UPSTREAM_SENDING; 4.447 + p->state = STATE_IOREQ_READY; 4.448 + 4.449 + // Try to use ins/outs' framework 4.450 + if (pvalid) { 4.451 + // Handle "movs" 4.452 + p->u.pdata = (void *) ((p->dir == IOREQ_WRITE) ? 4.453 + inst_decoder_regs->esi 4.454 + : inst_decoder_regs->edi); 4.455 + p->u.pdata = (void *) gva_to_gpa(p->u.data); 4.456 + p->count = inst_decoder_regs->ecx; 4.457 + inst_decoder_regs->ecx = 0; 4.458 + p->df = (inst_decoder_regs->eflags & EF_DF) ? 1 : 0; 4.459 + } 4.460 + 4.461 + evtchn_send(IOPACKET_PORT); 4.462 + do_block(); 4.463 + 4.464 +} 4.465 + 4.466 +void handle_mmio(unsigned long va, unsigned long gpte, unsigned long gpa) 4.467 +{ 4.468 + unsigned long eip; 4.469 + unsigned long inst_len; 4.470 + struct mi_per_cpu_info *mpci_p; 4.471 + struct xen_regs *inst_decoder_regs; 4.472 + struct instruction mmio_inst; 4.473 + unsigned char inst[MAX_INST_LEN]; 4.474 + int ret; 4.475 + 4.476 + mpci_p = ¤t->thread.arch_vmx.vmx_platform.mpci; 4.477 + inst_decoder_regs = mpci_p->inst_decoder_regs; 4.478 + 4.479 + __vmread(GUEST_EIP, &eip); 4.480 + __vmread(INSTRUCTION_LEN, &inst_len); 4.481 + 4.482 + memset(inst, '0', MAX_INST_LEN); 4.483 + ret = inst_copy_from_guest(inst, eip, inst_len); 4.484 + if (ret != inst_len) { 4.485 + printk("handle_mmio - EXIT: get guest instruction fault\n"); 4.486 + domain_crash(); 4.487 + } 4.488 + 4.489 + init_instruction(&mmio_inst); 4.490 + 4.491 + if (vmx_decode(check_prefix(inst, &mmio_inst), &mmio_inst) == DECODE_failure) 4.492 + domain_crash(); 4.493 + 4.494 + __vmwrite(GUEST_EIP, eip + inst_len); 4.495 + store_xen_regs(inst_decoder_regs); 4.496 + 4.497 + // Only handle "mov" and "movs" instructions! 4.498 + if (!strncmp(mmio_inst.i_name, "movzw", 5)) { 4.499 + long value = 0; 4.500 + int index; 4.501 + 4.502 + if (read_from_mmio(&mmio_inst)) { 4.503 + // Send the request and waiting for return value. 4.504 + mpci_p->mmio_target = mmio_inst.operand[1] | WZEROEXTEND; 4.505 + mmio_inst.op_size = WORD; 4.506 + send_mmio_req(gpa, &mmio_inst, value, 1, 0); 4.507 + } else { 4.508 + // Write to MMIO 4.509 + if (mmio_inst.operand[0] & IMMEDIATE) { 4.510 + value = mmio_inst.immediate; 4.511 + } else if (mmio_inst.operand[0] & REGISTER) { 4.512 + index = operand_index(mmio_inst.operand[0]); 4.513 + value = get_reg_value(WORD, index, 0, inst_decoder_regs); 4.514 + } else { 4.515 + domain_crash(); 4.516 + } 4.517 + mmio_inst.op_size = WORD; 4.518 + send_mmio_req(gpa, &mmio_inst, value, 0, 0); 4.519 + return; 4.520 + } 4.521 + } 4.522 + 4.523 + if (!strncmp(mmio_inst.i_name, "movs", 4)) { 4.524 + int tmp_dir; 4.525 + 4.526 + tmp_dir = ((va == inst_decoder_regs->edi) ? IOREQ_WRITE : IOREQ_READ); 4.527 + send_mmio_req(gpa, &mmio_inst, 0, tmp_dir, 1); 4.528 + return; 4.529 + } 4.530 + 4.531 + if (!strncmp(mmio_inst.i_name, "mov", 3)) { 4.532 + long value = 0; 4.533 + int size, index; 4.534 + 4.535 + if (read_from_mmio(&mmio_inst)) { 4.536 + // Send the request and waiting for return value. 4.537 + mpci_p->mmio_target = mmio_inst.operand[1]; 4.538 + send_mmio_req(gpa, &mmio_inst, value, 1, 0); 4.539 + } else { 4.540 + // Write to MMIO 4.541 + if (mmio_inst.operand[0] & IMMEDIATE) { 4.542 + value = mmio_inst.immediate; 4.543 + } else if (mmio_inst.operand[0] & REGISTER) { 4.544 + size = operand_size(mmio_inst.operand[0]); 4.545 + index = operand_index(mmio_inst.operand[0]); 4.546 + value = get_reg_value(size, index, 0, inst_decoder_regs); 4.547 + } else { 4.548 + domain_crash(); 4.549 + } 4.550 + send_mmio_req(gpa, &mmio_inst, value, 0, 0); 4.551 + return; 4.552 + } 4.553 + domain_crash(); 4.554 + } 4.555 + domain_crash(); 4.556 +} 4.557 +
5.1 --- a/xen/include/asm-x86/shadow.h Thu Jan 27 23:49:46 2005 +0000 5.2 +++ b/xen/include/asm-x86/shadow.h Thu Jan 27 23:53:26 2005 +0000 5.3 @@ -305,10 +305,15 @@ static inline void l1pte_propagate_from_ 5.4 case SHM_full_32: 5.5 { 5.6 unsigned long host_pfn, host_gpte; 5.7 + spte = 0; 5.8 + 5.9 + if (mmio_space(gpte & 0xFFFFF000)) { 5.10 + *spte_p = spte; 5.11 + return; 5.12 + } 5.13 5.14 host_pfn = phys_to_machine_mapping[gpte >> PAGE_SHIFT]; 5.15 host_gpte = (host_pfn << PAGE_SHIFT) | (gpte & ~PAGE_MASK); 5.16 - spte = 0; 5.17 5.18 if ( (host_gpte & (_PAGE_PRESENT|_PAGE_ACCESSED) ) == 5.19 (_PAGE_PRESENT|_PAGE_ACCESSED) ) 5.20 @@ -697,7 +702,7 @@ static inline void __shadow_mk_pagetable 5.21 SH_VVLOG("__shadow_mk_pagetable(guest_gpfn=%08lx, gpfn=%08lx\n", 5.22 guest_gpfn, gpfn); 5.23 5.24 - spfn = __shadow_status(mm, gpfn) & PSH_pfn_mask; 5.25 + spfn = __shadow_status(mm, guest_gpfn) & PSH_pfn_mask; 5.26 if ( unlikely(spfn == 0) ) { 5.27 spfn = shadow_l2_table(mm, gpfn); 5.28 mm->shadow_table = mk_pagetable(spfn<<PAGE_SHIFT);
6.1 --- a/xen/include/asm-x86/vmx_platform.h Thu Jan 27 23:49:46 2005 +0000 6.2 +++ b/xen/include/asm-x86/vmx_platform.h Thu Jan 27 23:53:26 2005 +0000 6.3 @@ -19,6 +19,78 @@ 6.4 #ifndef __ASM_X86_VMX_PLATFORM_H__ 6.5 #define __ASM_X86_VMX_PLATFORM_H__ 6.6 6.7 -#include <asm/e820.h> /* from Linux */ 6.8 +#include <asm/e820.h> /* from Linux */ 6.9 + 6.10 +#define MAX_OPERAND_NUM 3 6.11 +#define I_NAME_LEN 16 6.12 + 6.13 +#define mk_operand(size, index, seg, flag) \ 6.14 + (((size) << 24) | ((index) << 16) | ((seg) << 8) | (flag)) 6.15 + 6.16 +#define operand_size(operand) \ 6.17 + ((operand >> 24) & 0xFF) 6.18 + 6.19 +#define operand_index(operand) \ 6.20 + ((operand >> 16) & 0xFF) 6.21 + //For instruction.operand[].size 6.22 +#define BYTE 1 6.23 +#define WORD 2 6.24 +#define LONG 4 6.25 +#define QUAD 8 6.26 + 6.27 + //For instruction.operand[].flag 6.28 +#define REGISTER 0x1 6.29 +#define MEMORY 0x2 6.30 +#define IMMEDIATE 0x4 6.31 +#define WZEROEXTEND 0x8 6.32 + 6.33 + //For instruction.flags 6.34 +#define REPZ 0x1 6.35 +#define REPNZ 0x2 6.36 + 6.37 +struct instruction { 6.38 + __s8 i_name[I_NAME_LEN]; //Instruction's name 6.39 + __s16 op_size; //The operand's bit size, e.g. 16-bit or 32-bit. 6.40 + 6.41 + __u64 offset; //The effective address 6.42 + //offset = Base + (Index * Scale) + Displacement 6.43 + 6.44 + __u64 immediate; 6.45 + 6.46 + __u16 seg_sel; //Segmentation selector 6.47 + 6.48 + __u32 operand[MAX_OPERAND_NUM]; //The order of operand is from AT&T Assembly 6.49 + __s16 op_num; //The operand numbers 6.50 + 6.51 + __u32 flags; // 6.52 +}; 6.53 + 6.54 +#define VGA_SPACE_START 0xA0000 6.55 +#define VGA_SPACE_END 0xC0000 6.56 +#define MAX_INST_LEN 32 6.57 + 6.58 +struct mi_per_cpu_info 6.59 +{ 6.60 + unsigned long mmio_target; 6.61 + struct xen_regs *inst_decoder_regs; 6.62 +}; 6.63 + 6.64 +struct virutal_platform_def { 6.65 + unsigned long *real_mode_data; /* E820, etc. */ 6.66 + unsigned long shared_page_va; 6.67 + struct mi_per_cpu_info mpci; /* MMIO */ 6.68 +}; 6.69 + 6.70 +extern int mmio_space(unsigned long); 6.71 +extern void handle_mmio(unsigned long, unsigned long, unsigned long); 6.72 +extern int vmx_setup_platform(struct exec_domain *, execution_context_t *); 6.73 + 6.74 +extern inline int mmio_space(unsigned long gpa) 6.75 +{ 6.76 + if (gpa >= VGA_SPACE_START && gpa < VGA_SPACE_END) { 6.77 + return 1; 6.78 + } 6.79 + return 0; 6.80 +} 6.81 6.82 #endif
7.1 --- a/xen/include/asm-x86/vmx_vmcs.h Thu Jan 27 23:49:46 2005 +0000 7.2 +++ b/xen/include/asm-x86/vmx_vmcs.h Thu Jan 27 23:53:26 2005 +0000 7.3 @@ -39,15 +39,7 @@ union vmcs_arbytes { 7.4 unsigned int bytes; 7.5 }; 7.6 7.7 -struct virutal_platform_def { 7.8 - unsigned long *real_mode_data; /* E820, etc. */ 7.9 - unsigned long shared_page_va; 7.10 -}; 7.11 - 7.12 -int vmx_setup_platform(struct exec_domain *, execution_context_t *); 7.13 - 7.14 #define VMX_CPU_STATE_PG_ENABLED 0 7.15 - 7.16 #define VMCS_SIZE 0x1000 7.17 7.18 struct vmcs_struct { 7.19 @@ -62,10 +54,6 @@ struct arch_vmx_struct { 7.20 unsigned long cpu_cr3; 7.21 unsigned long cpu_state; 7.22 struct virutal_platform_def vmx_platform; 7.23 -#if 0 7.24 - /* open */ 7.25 - unsigned long *page_list; /* page list for MMIO */ 7.26 -#endif 7.27 }; 7.28 7.29 #define vmx_schedule_tail(next) \