ia64/xen-unstable

annotate xen/arch/x86/hvm/svm/svm.c @ 10892:0d2ba35c0cf2

[XEN] Add hypercall support for HVM guests. This is
fairly useless at the moment, since all of the hypercalls
fail, since copy_from_user doesn't work correctly in HVM
domains.

Signed-off-by: Steven Smith <ssmith@xensource.com>

Add a CPUID hypervisor platform interface at leaf
0x40000000. Allow hypercall transfer page to be filled
in via MSR 0x40000000.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Tue Aug 01 17:18:05 2006 +0100 (2006-08-01)
parents 7137825805c7
children 2e3b121662dc
rev   line source
kaf24@8708 1 /*
kaf24@8708 2 * svm.c: handling SVM architecture-related VM exits
kaf24@8708 3 * Copyright (c) 2004, Intel Corporation.
kaf24@8708 4 * Copyright (c) 2005, AMD Corporation.
kaf24@8708 5 *
kaf24@8708 6 * This program is free software; you can redistribute it and/or modify it
kaf24@8708 7 * under the terms and conditions of the GNU General Public License,
kaf24@8708 8 * version 2, as published by the Free Software Foundation.
kaf24@8708 9 *
kaf24@8708 10 * This program is distributed in the hope it will be useful, but WITHOUT
kaf24@8708 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
kaf24@8708 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
kaf24@8708 13 * more details.
kaf24@8708 14 *
kaf24@8708 15 * You should have received a copy of the GNU General Public License along with
kaf24@8708 16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
kaf24@8708 17 * Place - Suite 330, Boston, MA 02111-1307 USA.
kaf24@8708 18 *
kaf24@8708 19 */
kaf24@8708 20
kaf24@8708 21 #include <xen/config.h>
kaf24@8708 22 #include <xen/init.h>
kaf24@8708 23 #include <xen/lib.h>
kaf24@8708 24 #include <xen/trace.h>
kaf24@8708 25 #include <xen/sched.h>
kaf24@8708 26 #include <xen/irq.h>
kaf24@8708 27 #include <xen/softirq.h>
kaf24@8708 28 #include <asm/current.h>
kaf24@8708 29 #include <asm/io.h>
kaf24@8708 30 #include <asm/shadow.h>
kaf24@8708 31 #include <asm/regs.h>
kaf24@8708 32 #include <asm/cpufeature.h>
kaf24@8708 33 #include <asm/processor.h>
kaf24@8708 34 #include <asm/types.h>
kaf24@8708 35 #include <asm/msr.h>
kaf24@8708 36 #include <asm/spinlock.h>
kaf24@8708 37 #include <asm/hvm/hvm.h>
kaf24@8708 38 #include <asm/hvm/support.h>
kaf24@8708 39 #include <asm/hvm/io.h>
kaf24@8708 40 #include <asm/hvm/svm/svm.h>
kaf24@8708 41 #include <asm/hvm/svm/vmcb.h>
kaf24@8708 42 #include <asm/hvm/svm/emulate.h>
kaf24@8708 43 #include <asm/hvm/svm/vmmcall.h>
kaf24@8708 44 #include <asm/hvm/svm/intr.h>
kaf24@8708 45 #include <asm/shadow.h>
kaf24@8708 46 #if CONFIG_PAGING_LEVELS >= 3
kaf24@8708 47 #include <asm/shadow_64.h>
kaf24@8708 48 #endif
kaf24@8708 49 #include <public/sched.h>
kaf24@8708 50
kaf24@8708 51 #define SVM_EXTRA_DEBUG
kaf24@8708 52
kaf24@9942 53 #define set_segment_register(name, value) \
kaf24@9942 54 __asm__ __volatile__ ( "movw %%ax ,%%" STR(name) "" : : "a" (value) )
kaf24@9942 55
kaf24@8708 56 /*
kaf24@8708 57 * External functions, etc. We should move these to some suitable header file(s) */
kaf24@8708 58
kaf24@8708 59 extern void do_nmi(struct cpu_user_regs *, unsigned long);
kaf24@8708 60 extern int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip,
kaf24@8708 61 int inst_len);
kaf24@8708 62 extern asmlinkage void do_IRQ(struct cpu_user_regs *);
kaf24@8708 63 extern void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
kaf24@8708 64 unsigned long count, int size, long value, int dir, int pvalid);
kaf24@8708 65 extern int svm_instrlen(struct cpu_user_regs *regs, int mode);
kaf24@8708 66 extern void svm_dump_inst(unsigned long eip);
kaf24@8708 67 extern int svm_dbg_on;
kaf24@8708 68 void svm_dump_regs(const char *from, struct cpu_user_regs *regs);
kaf24@8708 69
kaf24@9304 70 static void svm_relinquish_guest_resources(struct domain *d);
kaf24@10212 71 static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v,
kaf24@10212 72 struct cpu_user_regs *regs);
kaf24@10212 73
kaf24@9304 74
kaf24@10084 75
kaf24@10084 76 extern void set_hsa_to_guest( struct arch_svm_struct *arch_svm );
kaf24@10084 77
kaf24@10084 78 /* Host save area and ASID glogal data */
kaf24@10084 79 struct svm_percore_globals svm_globals[NR_CPUS];
kaf24@8708 80
kaf24@8708 81 /*
kaf24@8708 82 * Initializes the POOL of ASID used by the guests per core.
kaf24@8708 83 */
kaf24@10288 84 void asidpool_init(int core)
kaf24@8708 85 {
kaf24@8708 86 int i;
kaf24@10288 87
kaf24@10288 88 spin_lock_init(&svm_globals[core].ASIDpool.asid_lock);
kaf24@10288 89
kaf24@8708 90 /* Host ASID is always in use */
kaf24@10084 91 svm_globals[core].ASIDpool.asid[INITIAL_ASID] = ASID_INUSE;
kaf24@10288 92 for ( i = 1; i < ASID_MAX; i++ )
kaf24@10084 93 svm_globals[core].ASIDpool.asid[i] = ASID_AVAILABLE;
kaf24@8708 94 }
kaf24@8708 95
kaf24@8708 96
kaf24@8708 97 /* internal function to get the next available ASID */
kaf24@10288 98 static int asidpool_fetch_next(struct vmcb_struct *vmcb, int core)
kaf24@8708 99 {
kaf24@8708 100 int i;
kaf24@10288 101 for ( i = 1; i < ASID_MAX; i++ )
kaf24@8708 102 {
kaf24@10288 103 if ( svm_globals[core].ASIDpool.asid[i] == ASID_AVAILABLE )
kaf24@8708 104 {
kaf24@8708 105 vmcb->guest_asid = i;
kaf24@10084 106 svm_globals[core].ASIDpool.asid[i] = ASID_INUSE;
kaf24@8708 107 return i;
kaf24@8708 108 }
kaf24@8708 109 }
kaf24@8708 110 return -1;
kaf24@8708 111 }
kaf24@8708 112
kaf24@8708 113
kaf24@8708 114 /*
kaf24@8708 115 * This functions assigns on the passed VMCB, the next
kaf24@8708 116 * available ASID number. If none are available, the
kaf24@8708 117 * TLB flush flag is set, and all retireds ASID
kaf24@8708 118 * are made available.
kaf24@8708 119 *
kaf24@8708 120 * Returns: 1 -- sucess;
kaf24@8708 121 * 0 -- failure -- no more ASID numbers
kaf24@8708 122 * available.
kaf24@8708 123 */
kaf24@8708 124 int asidpool_assign_next( struct vmcb_struct *vmcb, int retire_current,
kaf24@8708 125 int oldcore, int newcore )
kaf24@8708 126 {
kaf24@8708 127 int i;
kaf24@8708 128 int res = 1;
kaf24@8708 129 static unsigned long cnt=0;
kaf24@8708 130
kaf24@10084 131 spin_lock(&svm_globals[oldcore].ASIDpool.asid_lock);
kaf24@8708 132 if( retire_current && vmcb->guest_asid ) {
kaf24@10084 133 svm_globals[oldcore].ASIDpool.asid[ vmcb->guest_asid & (ASID_MAX-1) ] = ASID_RETIRED;
kaf24@8708 134 }
kaf24@10084 135 spin_unlock(&svm_globals[oldcore].ASIDpool.asid_lock);
kaf24@10084 136 spin_lock(&svm_globals[newcore].ASIDpool.asid_lock);
kaf24@8708 137 if( asidpool_fetch_next( vmcb, newcore ) < 0 ) {
kaf24@8708 138 if (svm_dbg_on)
kaf24@8708 139 printk( "SVM: tlb(%ld)\n", cnt++ );
kaf24@8708 140 /* FLUSH the TLB and all retired slots are made available */
kaf24@8708 141 vmcb->tlb_control = 1;
kaf24@8708 142 for( i = 1; i < ASID_MAX; i++ ) {
kaf24@10084 143 if( svm_globals[newcore].ASIDpool.asid[i] == ASID_RETIRED ) {
kaf24@10084 144 svm_globals[newcore].ASIDpool.asid[i] = ASID_AVAILABLE;
kaf24@8708 145 }
kaf24@8708 146 }
kaf24@8708 147 /* Get the First slot available */
kaf24@8708 148 res = asidpool_fetch_next( vmcb, newcore ) > 0;
kaf24@8708 149 }
kaf24@10084 150 spin_unlock(&svm_globals[newcore].ASIDpool.asid_lock);
kaf24@8708 151 return res;
kaf24@8708 152 }
kaf24@8708 153
kaf24@8708 154 void asidpool_retire( struct vmcb_struct *vmcb, int core )
kaf24@8708 155 {
kaf24@10084 156 spin_lock(&svm_globals[core].ASIDpool.asid_lock);
kaf24@8708 157 if( vmcb->guest_asid ) {
kaf24@10084 158 svm_globals[core].ASIDpool.asid[ vmcb->guest_asid & (ASID_MAX-1) ] = ASID_RETIRED;
kaf24@8708 159 }
kaf24@10084 160 spin_unlock(&svm_globals[core].ASIDpool.asid_lock);
kaf24@8708 161 }
kaf24@8708 162
kaf24@10082 163 static inline void svm_inject_exception(struct vcpu *v, int trap, int ev, int error_code)
kaf24@8708 164 {
kaf24@8893 165 eventinj_t event;
kaf24@10082 166 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8893 167
kaf24@8893 168 event.bytes = 0;
kaf24@8893 169 event.fields.v = 1;
kaf24@8893 170 event.fields.type = EVENTTYPE_EXCEPTION;
kaf24@8893 171 event.fields.vector = trap;
kaf24@9073 172 event.fields.ev = ev;
kaf24@8893 173 event.fields.errorcode = error_code;
kaf24@8893 174
kaf24@8896 175 ASSERT(vmcb->eventinj.fields.v == 0);
kaf24@8893 176
kaf24@8893 177 vmcb->eventinj = event;
kaf24@8708 178 }
kaf24@8708 179
kaf24@8708 180 void stop_svm(void)
kaf24@8708 181 {
kaf24@8708 182 u32 eax, edx;
kaf24@9929 183 int cpu = smp_processor_id();
kaf24@8708 184
kaf24@8708 185 /* We turn off the EFER_SVME bit. */
kaf24@8708 186 rdmsr(MSR_EFER, eax, edx);
kaf24@8708 187 eax &= ~EFER_SVME;
kaf24@8708 188 wrmsr(MSR_EFER, eax, edx);
kaf24@9929 189
kaf24@9929 190 /* release the HSA */
kaf24@10084 191 free_host_save_area( svm_globals[cpu].hsa );
kaf24@10084 192 free_host_save_area( svm_globals[cpu].scratch_hsa );
kaf24@10084 193 svm_globals[cpu].hsa = NULL;
kaf24@10084 194 svm_globals[cpu].hsa_pa = 0;
kaf24@10084 195 svm_globals[cpu].scratch_hsa = NULL;
kaf24@10084 196 svm_globals[cpu].scratch_hsa_pa = 0;
kaf24@10084 197 wrmsr(MSR_K8_VM_HSAVE_PA, 0, 0 );
kaf24@8708 198
kaf24@8708 199 printk("AMD SVM Extension is disabled.\n");
kaf24@8708 200 }
kaf24@8708 201
kaf24@8708 202 int svm_initialize_guest_resources(struct vcpu *v)
kaf24@8708 203 {
kaf24@8708 204 svm_final_setup_guest(v);
kaf24@8708 205 return 1;
kaf24@8708 206 }
kaf24@8708 207
kaf24@9333 208 static void svm_store_cpu_guest_regs(
kaf24@9436 209 struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs)
kaf24@8708 210 {
kaf24@8708 211 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 212
kaf24@9436 213 if ( regs != NULL )
kaf24@9436 214 {
kaf24@9436 215 regs->eip = vmcb->rip;
kaf24@9436 216 regs->esp = vmcb->rsp;
kaf24@9436 217 regs->eflags = vmcb->rflags;
kaf24@9436 218 regs->cs = vmcb->cs.sel;
kaf24@9436 219 regs->ds = vmcb->ds.sel;
kaf24@9436 220 regs->es = vmcb->es.sel;
kaf24@9436 221 regs->ss = vmcb->ss.sel;
kaf24@9436 222 regs->gs = vmcb->gs.sel;
kaf24@9436 223 regs->fs = vmcb->fs.sel;
kaf24@9436 224 }
kaf24@9436 225
kaf24@9436 226 if ( crs != NULL )
kaf24@9436 227 {
kaf24@10549 228 /* Returning the guest's regs */
kaf24@10549 229 crs[0] = v->arch.hvm_svm.cpu_shadow_cr0;
kaf24@10549 230 crs[3] = v->arch.hvm_svm.cpu_cr3;
kaf24@10549 231 crs[4] = v->arch.hvm_svm.cpu_shadow_cr4;
kaf24@9436 232 }
kaf24@8708 233 }
kaf24@8708 234
kaf24@9333 235 static void svm_load_cpu_guest_regs(
kaf24@9333 236 struct vcpu *v, struct cpu_user_regs *regs)
kaf24@8708 237 {
kaf24@8708 238 svm_load_cpu_user_regs(v, regs);
kaf24@8708 239 }
kaf24@8708 240
kaf24@8708 241 #define IS_CANO_ADDRESS(add) 1
kaf24@8708 242
kaf24@8708 243 static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
kaf24@8708 244 {
kaf24@8708 245 u64 msr_content = 0;
kaf24@8708 246 struct vcpu *vc = current;
kaf24@8708 247 struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
kaf24@8708 248
kaf24@8708 249 switch (regs->ecx)
kaf24@8708 250 {
kaf24@8708 251 case MSR_EFER:
kaf24@9073 252 msr_content = vmcb->efer;
kaf24@9073 253 msr_content &= ~EFER_SVME;
kaf24@8708 254 break;
kaf24@8708 255
kaf24@8708 256 case MSR_FS_BASE:
kaf24@8708 257 msr_content = vmcb->fs.base;
kaf24@8708 258 break;
kaf24@8708 259
kaf24@8708 260 case MSR_GS_BASE:
kaf24@8708 261 msr_content = vmcb->gs.base;
kaf24@8708 262 break;
kaf24@8708 263
kaf24@8708 264 case MSR_SHADOW_GS_BASE:
kaf24@9073 265 msr_content = vmcb->kerngsbase;
kaf24@8708 266 break;
kaf24@8708 267
kaf24@9073 268 case MSR_STAR:
kaf24@9073 269 msr_content = vmcb->star;
kaf24@9073 270 break;
kaf24@9073 271
kaf24@9073 272 case MSR_LSTAR:
kaf24@9073 273 msr_content = vmcb->lstar;
kaf24@9073 274 break;
kaf24@9073 275
kaf24@9073 276 case MSR_CSTAR:
kaf24@9073 277 msr_content = vmcb->cstar;
kaf24@9073 278 break;
kaf24@9073 279
kaf24@9073 280 case MSR_SYSCALL_MASK:
kaf24@9073 281 msr_content = vmcb->sfmask;
kaf24@9073 282 break;
kaf24@9073 283
kaf24@8708 284 default:
kaf24@8708 285 return 0;
kaf24@8708 286 }
kaf24@8708 287
kaf24@9099 288 HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %"PRIx64"\n",
kaf24@8708 289 msr_content);
kaf24@8708 290
kaf24@8708 291 regs->eax = msr_content & 0xffffffff;
kaf24@8708 292 regs->edx = msr_content >> 32;
kaf24@8708 293 return 1;
kaf24@8708 294 }
kaf24@8708 295
kaf24@8708 296 static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
kaf24@8708 297 {
kaf24@8708 298 u64 msr_content = regs->eax | ((u64)regs->edx << 32);
kaf24@8708 299 struct vcpu *vc = current;
kaf24@8708 300 struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
kaf24@8708 301
kaf24@9099 302 HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx "
kaf24@9099 303 "msr_content %"PRIx64"\n",
kaf24@9099 304 (unsigned long)regs->ecx, msr_content);
kaf24@8708 305
kaf24@8708 306 switch (regs->ecx)
kaf24@8708 307 {
kaf24@8708 308 case MSR_EFER:
kaf24@9089 309 #ifdef __x86_64__
kaf24@9703 310 /* offending reserved bit will cause #GP */
kaf24@9703 311 if ( msr_content & ~(EFER_LME | EFER_LMA | EFER_NX | EFER_SCE) )
kaf24@8708 312 {
kaf24@9703 313 printk("trying to set reserved bit in EFER\n");
kaf24@10082 314 svm_inject_exception(vc, TRAP_gp_fault, 1, 0);
kaf24@9703 315 return 0;
kaf24@9703 316 }
kaf24@9703 317
kaf24@9703 318 /* LME: 0 -> 1 */
kaf24@9703 319 if ( msr_content & EFER_LME &&
kaf24@9703 320 !test_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state) )
kaf24@9703 321 {
kaf24@9703 322 if ( svm_paging_enabled(vc) ||
kaf24@9703 323 !test_bit(SVM_CPU_STATE_PAE_ENABLED,
kaf24@9703 324 &vc->arch.hvm_svm.cpu_state) )
kaf24@8708 325 {
kaf24@9703 326 printk("trying to set LME bit when "
kaf24@9703 327 "in paging mode or PAE bit is not set\n");
kaf24@10082 328 svm_inject_exception(vc, TRAP_gp_fault, 1, 0);
kaf24@9703 329 return 0;
kaf24@8708 330 }
kaf24@9703 331 set_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state);
kaf24@8708 332 }
kaf24@8708 333
kaf24@9073 334 /* We have already recorded that we want LME, so it will be set
kaf24@9073 335 * next time CR0 gets updated. So we clear that bit and continue.
kaf24@9073 336 */
kaf24@9073 337 if ((msr_content ^ vmcb->efer) & EFER_LME)
kaf24@9073 338 msr_content &= ~EFER_LME;
kaf24@8708 339 /* No update for LME/LMA since it have no effect */
kaf24@9089 340 #endif
kaf24@9073 341 vmcb->efer = msr_content | EFER_SVME;
kaf24@8708 342 break;
kaf24@8708 343
kaf24@8708 344 case MSR_FS_BASE:
kaf24@8708 345 case MSR_GS_BASE:
kaf24@8708 346 if (!(SVM_LONG_GUEST(vc)))
kaf24@8708 347 domain_crash_synchronous();
kaf24@8708 348
kaf24@8708 349 if (!IS_CANO_ADDRESS(msr_content))
kaf24@8708 350 {
kaf24@8708 351 HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n");
kaf24@10082 352 svm_inject_exception(vc, TRAP_gp_fault, 1, 0);
kaf24@8708 353 }
kaf24@8708 354
kaf24@8708 355 if (regs->ecx == MSR_FS_BASE)
kaf24@9073 356 vmcb->fs.base = msr_content;
kaf24@8708 357 else
kaf24@9073 358 vmcb->gs.base = msr_content;
kaf24@8708 359 break;
kaf24@8708 360
kaf24@8708 361 case MSR_SHADOW_GS_BASE:
kaf24@9073 362 vmcb->kerngsbase = msr_content;
kaf24@9073 363 break;
kaf24@9073 364
kaf24@9073 365 case MSR_STAR:
kaf24@9073 366 vmcb->star = msr_content;
kaf24@9073 367 break;
kaf24@9073 368
kaf24@9073 369 case MSR_LSTAR:
kaf24@9073 370 vmcb->lstar = msr_content;
kaf24@9073 371 break;
kaf24@9073 372
kaf24@9073 373 case MSR_CSTAR:
kaf24@9073 374 vmcb->cstar = msr_content;
kaf24@9073 375 break;
kaf24@9073 376
kaf24@9073 377 case MSR_SYSCALL_MASK:
kaf24@9073 378 vmcb->sfmask = msr_content;
kaf24@9073 379 break;
kaf24@9073 380
kaf24@8708 381 default:
kaf24@8708 382 return 0;
kaf24@8708 383 }
kaf24@8708 384 return 1;
kaf24@8708 385 }
kaf24@8708 386
kaf24@8708 387 int svm_realmode(struct vcpu *v)
kaf24@8708 388 {
kaf24@8708 389 unsigned long cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
kaf24@8708 390 unsigned long eflags = v->arch.hvm_svm.vmcb->rflags;
kaf24@8708 391
kaf24@8708 392 return (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
kaf24@8708 393 }
kaf24@8708 394
kaf24@8708 395 int svm_instruction_length(struct vcpu *v)
kaf24@8708 396 {
kaf24@8708 397 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 398 unsigned long cr0 = vmcb->cr0, eflags = vmcb->rflags, mode;
kaf24@9073 399 /* check which operating mode the guest is running */
kaf24@9073 400 if( vmcb->efer & EFER_LMA )
kaf24@9073 401 mode = vmcb->cs.attributes.fields.l ? 8 : 4;
kaf24@9073 402 else
kaf24@9073 403 mode = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE) ? 2 : 4;
kaf24@8708 404 return svm_instrlen(guest_cpu_user_regs(), mode);
kaf24@8708 405 }
kaf24@8708 406
kaf24@9073 407 unsigned long svm_get_ctrl_reg(struct vcpu *v, unsigned int num)
kaf24@9073 408 {
kaf24@9073 409 switch ( num )
kaf24@9073 410 {
kaf24@9073 411 case 0:
kaf24@9073 412 return v->arch.hvm_svm.cpu_shadow_cr0;
kaf24@9073 413 case 2:
kaf24@9073 414 return v->arch.hvm_svm.cpu_cr2;
kaf24@9073 415 case 3:
kaf24@9073 416 return v->arch.hvm_svm.cpu_cr3;
kaf24@9073 417 default:
kaf24@9073 418 BUG();
kaf24@9073 419 }
kaf24@9073 420 return 0; /* dummy */
kaf24@9073 421 }
kaf24@9073 422
kaf24@10212 423
kaf24@10212 424 /* SVM-specific intitialization code for VCPU application processors */
kaf24@10212 425 void svm_init_ap_context(struct vcpu_guest_context *ctxt,
kaf24@10212 426 int vcpuid, int trampoline_vector)
kaf24@10212 427 {
kaf24@10212 428 int i;
kaf24@10212 429 struct vcpu *v, *bsp = current;
kaf24@10212 430 struct domain *d = bsp->domain;
kaf24@10212 431 cpu_user_regs_t *regs;;
kaf24@10212 432
kaf24@10212 433
kaf24@10212 434 if ((v = d->vcpu[vcpuid]) == NULL)
kaf24@10212 435 {
kaf24@10212 436 printk("vcpuid %d is invalid! good-bye.\n", vcpuid);
kaf24@10212 437 domain_crash_synchronous();
kaf24@10212 438 }
kaf24@10212 439 regs = &v->arch.guest_context.user_regs;
kaf24@10212 440
kaf24@10212 441 memset(ctxt, 0, sizeof(*ctxt));
kaf24@10212 442 for (i = 0; i < 256; ++i)
kaf24@10212 443 {
kaf24@10212 444 ctxt->trap_ctxt[i].vector = i;
kaf24@10212 445 ctxt->trap_ctxt[i].cs = FLAT_KERNEL_CS;
kaf24@10212 446 }
kaf24@10212 447
kaf24@10212 448
kaf24@10212 449 /*
kaf24@10212 450 * We execute the trampoline code in real mode. The trampoline vector
kaf24@10212 451 * passed to us is page alligned and is the physicall frame number for
kaf24@10212 452 * the code. We will execute this code in real mode.
kaf24@10212 453 */
kaf24@10212 454 ctxt->user_regs.eip = 0x0;
kaf24@10212 455 ctxt->user_regs.cs = (trampoline_vector << 8);
kaf24@10212 456 ctxt->flags = VGCF_HVM_GUEST;
kaf24@10212 457 }
kaf24@10212 458
kfraser@10892 459 static void svm_init_hypercall_page(struct domain *d, void *hypercall_page)
kfraser@10892 460 {
kfraser@10892 461 char *p;
kfraser@10892 462 int i;
kfraser@10892 463
kfraser@10892 464 memset(hypercall_page, 0, PAGE_SIZE);
kfraser@10892 465
kfraser@10892 466 for ( i = 0; i < (PAGE_SIZE / 32); i++ )
kfraser@10892 467 {
kfraser@10892 468 p = (char *)(hypercall_page + (i * 32));
kfraser@10892 469 *(u8 *)(p + 0) = 0xb8; /* mov imm32, %eax */
kfraser@10892 470 *(u32 *)(p + 1) = i;
kfraser@10892 471 *(u8 *)(p + 5) = 0x0f; /* vmmcall */
kfraser@10892 472 *(u8 *)(p + 6) = 0x01;
kfraser@10892 473 *(u8 *)(p + 7) = 0xd9;
kfraser@10892 474 *(u8 *)(p + 8) = 0xc3; /* ret */
kfraser@10892 475 }
kfraser@10892 476
kfraser@10892 477 /* Don't support HYPERVISOR_iret at the moment */
kfraser@10892 478 *(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */
kfraser@10892 479 }
kfraser@10892 480
kaf24@8708 481 int start_svm(void)
kaf24@8708 482 {
kaf24@8708 483 u32 eax, ecx, edx;
kaf24@9929 484 u32 phys_hsa_lo, phys_hsa_hi;
kaf24@9929 485 u64 phys_hsa;
kaf24@9929 486 int cpu = smp_processor_id();
kaf24@9929 487
kaf24@9929 488 /* Xen does not fill x86_capability words except 0. */
kaf24@8708 489 ecx = cpuid_ecx(0x80000001);
kaf24@8708 490 boot_cpu_data.x86_capability[5] = ecx;
kaf24@8708 491
kaf24@8708 492 if (!(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)))
kaf24@8708 493 return 0;
kaf24@10110 494 svm_globals[cpu].hsa = alloc_host_save_area();
kaf24@10110 495 if (! svm_globals[cpu].hsa)
kaf24@10110 496 return 0;
kaf24@8708 497
kaf24@8708 498 rdmsr(MSR_EFER, eax, edx);
kaf24@8708 499 eax |= EFER_SVME;
kaf24@8708 500 wrmsr(MSR_EFER, eax, edx);
kaf24@10084 501 asidpool_init( cpu );
kaf24@9929 502 printk("AMD SVM Extension is enabled for cpu %d.\n", cpu );
kaf24@9929 503
kaf24@9929 504 /* Initialize the HSA for this core */
kaf24@10084 505 phys_hsa = (u64) virt_to_maddr( svm_globals[cpu].hsa );
kaf24@9929 506 phys_hsa_lo = (u32) phys_hsa;
kaf24@9929 507 phys_hsa_hi = (u32) (phys_hsa >> 32);
kaf24@9929 508 wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi);
kaf24@10084 509 svm_globals[cpu].hsa_pa = phys_hsa;
kaf24@10084 510
kaf24@10084 511 svm_globals[cpu].scratch_hsa = alloc_host_save_area();
kaf24@10084 512 svm_globals[cpu].scratch_hsa_pa = (u64)virt_to_maddr( svm_globals[cpu].scratch_hsa );
kaf24@10084 513
kaf24@8708 514 /* Setup HVM interfaces */
kaf24@8708 515 hvm_funcs.disable = stop_svm;
kaf24@8708 516
kaf24@8708 517 hvm_funcs.initialize_guest_resources = svm_initialize_guest_resources;
kaf24@8708 518 hvm_funcs.relinquish_guest_resources = svm_relinquish_guest_resources;
kaf24@8708 519
kaf24@8708 520 hvm_funcs.store_cpu_guest_regs = svm_store_cpu_guest_regs;
kaf24@8708 521 hvm_funcs.load_cpu_guest_regs = svm_load_cpu_guest_regs;
kaf24@8708 522
kaf24@8708 523 hvm_funcs.realmode = svm_realmode;
kaf24@8708 524 hvm_funcs.paging_enabled = svm_paging_enabled;
kaf24@8708 525 hvm_funcs.instruction_length = svm_instruction_length;
kaf24@9073 526 hvm_funcs.get_guest_ctrl_reg = svm_get_ctrl_reg;
kaf24@10212 527 hvm_funcs.init_ap_context = svm_init_ap_context;
kaf24@8708 528
kfraser@10892 529 hvm_funcs.init_hypercall_page = svm_init_hypercall_page;
kfraser@10892 530
kaf24@8708 531 hvm_enabled = 1;
kaf24@8708 532
kaf24@8708 533 return 1;
kaf24@8708 534 }
kaf24@8708 535
kaf24@8708 536 int svm_dbg_on = 0;
kaf24@8708 537
kaf24@8708 538 static inline int svm_do_debugout(unsigned long exit_code)
kaf24@8708 539 {
kaf24@8708 540 int i;
kaf24@8708 541
kaf24@8708 542 static unsigned long counter = 0;
kaf24@8708 543 static unsigned long works[] =
kaf24@8708 544 {
kaf24@8708 545 VMEXIT_IOIO,
kaf24@8708 546 VMEXIT_HLT,
kaf24@8708 547 VMEXIT_CPUID,
kaf24@8708 548 VMEXIT_DR0_READ,
kaf24@8708 549 VMEXIT_DR1_READ,
kaf24@8708 550 VMEXIT_DR2_READ,
kaf24@8708 551 VMEXIT_DR3_READ,
kaf24@8708 552 VMEXIT_DR6_READ,
kaf24@8708 553 VMEXIT_DR7_READ,
kaf24@8708 554 VMEXIT_DR0_WRITE,
kaf24@8708 555 VMEXIT_DR1_WRITE,
kaf24@8708 556 VMEXIT_DR2_WRITE,
kaf24@8708 557 VMEXIT_DR3_WRITE,
kaf24@8708 558 VMEXIT_CR0_READ,
kaf24@8708 559 VMEXIT_CR0_WRITE,
kaf24@8708 560 VMEXIT_CR3_READ,
kaf24@8708 561 VMEXIT_CR4_READ,
kaf24@8708 562 VMEXIT_MSR,
kaf24@8708 563 VMEXIT_CR0_WRITE,
kaf24@8708 564 VMEXIT_CR3_WRITE,
kaf24@8708 565 VMEXIT_CR4_WRITE,
kaf24@8708 566 VMEXIT_EXCEPTION_PF,
kaf24@8708 567 VMEXIT_INTR,
kaf24@8708 568 VMEXIT_INVLPG,
kaf24@8708 569 VMEXIT_EXCEPTION_NM
kaf24@8708 570 };
kaf24@8708 571
kaf24@8708 572
kaf24@8708 573 #if 0
kaf24@8708 574 if (svm_dbg_on && exit_code != 0x7B)
kaf24@8708 575 return 1;
kaf24@8708 576 #endif
kaf24@8708 577
kaf24@8708 578 counter++;
kaf24@8708 579
kaf24@8708 580 #if 0
kaf24@8708 581 if ((exit_code == 0x4E
kaf24@8708 582 || exit_code == VMEXIT_CR0_READ
kaf24@8708 583 || exit_code == VMEXIT_CR0_WRITE)
kaf24@8708 584 && counter < 200000)
kaf24@8708 585 return 0;
kaf24@8708 586
kaf24@8708 587 if ((exit_code == 0x4E) && counter < 500000)
kaf24@8708 588 return 0;
kaf24@8708 589 #endif
kaf24@8708 590
kaf24@8708 591 for (i = 0; i < sizeof(works) / sizeof(works[0]); i++)
kaf24@8708 592 if (exit_code == works[i])
kaf24@8708 593 return 0;
kaf24@8708 594
kaf24@8708 595 return 1;
kaf24@8708 596 }
kaf24@8708 597
kaf24@8708 598 void save_svm_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *ctxt)
kaf24@8708 599 {
kaf24@8708 600 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 601
kaf24@8708 602 ASSERT(vmcb);
kaf24@8708 603
kaf24@8708 604 ctxt->eax = vmcb->rax;
kaf24@8708 605 ctxt->ss = vmcb->ss.sel;
kaf24@8708 606 ctxt->esp = vmcb->rsp;
kaf24@8708 607 ctxt->eflags = vmcb->rflags;
kaf24@8708 608 ctxt->cs = vmcb->cs.sel;
kaf24@8708 609 ctxt->eip = vmcb->rip;
kaf24@8708 610
kaf24@8708 611 ctxt->gs = vmcb->gs.sel;
kaf24@8708 612 ctxt->fs = vmcb->fs.sel;
kaf24@8708 613 ctxt->es = vmcb->es.sel;
kaf24@8708 614 ctxt->ds = vmcb->ds.sel;
kaf24@8708 615 }
kaf24@8708 616
kaf24@8708 617 void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v)
kaf24@8708 618 {
kaf24@8708 619 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 620
kaf24@8708 621 regs->eip = vmcb->rip;
kaf24@8708 622 regs->esp = vmcb->rsp;
kaf24@8708 623 regs->eflags = vmcb->rflags;
kaf24@8708 624 regs->cs = vmcb->cs.sel;
kaf24@8708 625 regs->ds = vmcb->ds.sel;
kaf24@8708 626 regs->es = vmcb->es.sel;
kaf24@8708 627 regs->ss = vmcb->ss.sel;
kaf24@8708 628 }
kaf24@8708 629
kaf24@8708 630 /* XXX Use svm_load_cpu_guest_regs instead */
kaf24@8708 631 void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
kaf24@8708 632 {
kaf24@8708 633 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 634 u32 *intercepts = &v->arch.hvm_svm.vmcb->exception_intercepts;
kaf24@8708 635
kaf24@8708 636 /* Write the guest register value into VMCB */
kaf24@8708 637 vmcb->rax = regs->eax;
kaf24@8708 638 vmcb->ss.sel = regs->ss;
kaf24@8708 639 vmcb->rsp = regs->esp;
kaf24@8708 640 vmcb->rflags = regs->eflags;
kaf24@8708 641 vmcb->cs.sel = regs->cs;
kaf24@8708 642 vmcb->rip = regs->eip;
kaf24@8708 643 if (regs->eflags & EF_TF)
kaf24@8708 644 *intercepts |= EXCEPTION_BITMAP_DB;
kaf24@8708 645 else
kaf24@8708 646 *intercepts &= ~EXCEPTION_BITMAP_DB;
kaf24@8708 647 }
kaf24@8708 648
kaf24@8708 649 int svm_paging_enabled(struct vcpu *v)
kaf24@8708 650 {
kaf24@8708 651 unsigned long cr0;
kaf24@8708 652
kaf24@8708 653 cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
kaf24@8708 654
kaf24@8708 655 return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
kaf24@8708 656 }
kaf24@8708 657
kaf24@8708 658
kaf24@8708 659 /* Make sure that xen intercepts any FP accesses from current */
kaf24@8708 660 void svm_stts(struct vcpu *v)
kaf24@8708 661 {
kaf24@8708 662 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 663
kaf24@8852 664 /* FPU state already dirty? Then no need to setup_fpu() lazily. */
kaf24@8852 665 if ( test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )
kaf24@8852 666 return;
kaf24@8852 667
kaf24@8852 668 /*
kaf24@8852 669 * If the guest does not have TS enabled then we must cause and handle an
kaf24@8852 670 * exception on first use of the FPU. If the guest *does* have TS enabled
kaf24@8852 671 * then this is not necessary: no FPU activity can occur until the guest
kaf24@8852 672 * clears CR0.TS, and we will initialise the FPU when that happens.
kaf24@8852 673 */
kaf24@8852 674 if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) )
kaf24@8852 675 {
kaf24@8708 676 v->arch.hvm_svm.vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM;
kaf24@8852 677 vmcb->cr0 |= X86_CR0_TS;
kaf24@8852 678 }
kaf24@8708 679 }
kaf24@8708 680
kaf24@8708 681 static void arch_svm_do_launch(struct vcpu *v)
kaf24@8708 682 {
kaf24@8708 683 cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
kaf24@8708 684 int error;
kaf24@8708 685
kaf24@8708 686 #if 0
kaf24@8708 687 if (svm_dbg_on)
kaf24@8708 688 printk("Do launch\n");
kaf24@8708 689 #endif
kaf24@8708 690 error = construct_vmcb(&v->arch.hvm_svm, regs);
kaf24@8708 691 if ( error < 0 )
kaf24@8708 692 {
kaf24@8708 693 if (v->vcpu_id == 0) {
kaf24@8708 694 printk("Failed to construct a new VMCB for BSP.\n");
kaf24@8708 695 } else {
kaf24@8708 696 printk("Failed to construct a new VMCB for AP %d\n", v->vcpu_id);
kaf24@8708 697 }
kaf24@8708 698 domain_crash_synchronous();
kaf24@8708 699 }
kaf24@8708 700
kaf24@8708 701 svm_do_launch(v);
kaf24@8708 702 #if 0
kaf24@8708 703 if (svm_dbg_on)
kaf24@8708 704 svm_dump_host_regs(__func__);
kaf24@8708 705 #endif
kaf24@10212 706 if (v->vcpu_id != 0)
kaf24@10212 707 {
kaf24@10212 708 u16 cs_sel = regs->cs;
kaf24@10212 709 /*
kaf24@10212 710 * This is the launch of an AP; set state so that we begin executing
kaf24@10212 711 * the trampoline code in real-mode.
kaf24@10212 712 */
kaf24@10212 713 svm_do_vmmcall_reset_to_realmode(v, regs);
kaf24@10212 714 /* Adjust the state to execute the trampoline code.*/
kaf24@10212 715 v->arch.hvm_svm.vmcb->rip = 0;
kaf24@10212 716 v->arch.hvm_svm.vmcb->cs.sel= cs_sel;
kaf24@10212 717 v->arch.hvm_svm.vmcb->cs.base = (cs_sel << 4);
kaf24@10212 718 }
kaf24@10212 719
kaf24@8708 720 reset_stack_and_jump(svm_asm_do_launch);
kaf24@8708 721 }
kaf24@8708 722
kaf24@9416 723 static void svm_freeze_time(struct vcpu *v)
kaf24@9416 724 {
kaf24@10182 725 struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm;
kaf24@9416 726
kaf24@10182 727 if ( pt->enabled && pt->first_injected && !v->arch.hvm_vcpu.guest_time ) {
kaf24@10182 728 v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
kaf24@10182 729 stop_timer(&(pt->timer));
kaf24@9515 730 }
kaf24@9416 731 }
kaf24@9416 732
kaf24@9333 733 static void svm_ctxt_switch_from(struct vcpu *v)
kaf24@9333 734 {
kaf24@9416 735 svm_freeze_time(v);
kaf24@9333 736 }
kaf24@9333 737
kaf24@9333 738 static void svm_ctxt_switch_to(struct vcpu *v)
kaf24@9333 739 {
kaf24@9942 740 #if __x86_64__
kaf24@9942 741 /*
kaf24@9942 742 * This is required, because VMRUN does consistency check
kaf24@9942 743 * and some of the DOM0 selectors are pointing to
kaf24@9942 744 * invalid GDT locations, and cause AMD processors
kaf24@9942 745 * to shutdown.
kaf24@9942 746 */
kaf24@9942 747 set_segment_register(ds, 0);
kaf24@9942 748 set_segment_register(es, 0);
kaf24@9942 749 set_segment_register(ss, 0);
kaf24@9942 750 #endif
kaf24@9333 751 }
kaf24@9333 752
kaf24@8708 753 void svm_final_setup_guest(struct vcpu *v)
kaf24@8708 754 {
kaf24@10289 755 struct domain *d = v->domain;
kaf24@10289 756 struct vcpu *vc;
kaf24@10289 757
kaf24@9333 758 v->arch.schedule_tail = arch_svm_do_launch;
kaf24@9333 759 v->arch.ctxt_switch_from = svm_ctxt_switch_from;
kaf24@9333 760 v->arch.ctxt_switch_to = svm_ctxt_switch_to;
kaf24@8708 761
kaf24@10289 762 if ( v != d->vcpu[0] )
kaf24@10289 763 return;
kaf24@10289 764
kaf24@10289 765 /* Initialize monitor page table */
kaf24@10289 766 for_each_vcpu( d, vc )
kaf24@10289 767 vc->arch.monitor_table = pagetable_null();
kaf24@10289 768
kaf24@10289 769 /*
kaf24@10289 770 * Required to do this once per domain
kaf24@10289 771 * TODO: add a seperate function to do these.
kaf24@10289 772 */
kaf24@10289 773 memset(&d->shared_info->evtchn_mask[0], 0xff,
kaf24@10289 774 sizeof(d->shared_info->evtchn_mask));
kaf24@10289 775
kaf24@10289 776 /*
kaf24@10289 777 * Put the domain in shadow mode even though we're going to be using
kaf24@10289 778 * the shared 1:1 page table initially. It shouldn't hurt
kaf24@10289 779 */
kaf24@10289 780 shadow_mode_enable(d,
kaf24@10289 781 SHM_enable|SHM_refcounts|
kaf24@10289 782 SHM_translate|SHM_external|SHM_wr_pt_pte);
kaf24@8708 783 }
kaf24@8708 784
kaf24@8708 785
kaf24@9304 786 static void svm_relinquish_guest_resources(struct domain *d)
kaf24@8708 787 {
kaf24@8708 788 extern void destroy_vmcb(struct arch_svm_struct *); /* XXX */
kaf24@9304 789 struct vcpu *v;
kaf24@9304 790
kaf24@9304 791 for_each_vcpu ( d, v )
kaf24@9304 792 {
kaf24@9457 793 if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
kaf24@9457 794 continue;
kaf24@8708 795
kaf24@9304 796 destroy_vmcb(&v->arch.hvm_svm);
kaf24@9304 797 free_monitor_pagetable(v);
kaf24@9304 798 kill_timer(&v->arch.hvm_svm.hlt_timer);
kaf24@9304 799 if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) )
kaf24@9304 800 {
kaf24@9304 801 kill_timer( &(VLAPIC(v)->vlapic_timer) );
kaf24@9304 802 xfree(VLAPIC(v));
kaf24@9304 803 }
kaf24@8708 804 }
kaf24@8708 805
kaf24@10182 806 kill_timer(&d->arch.hvm_domain.pl_time.periodic_tm.timer);
kaf24@9304 807
kaf24@9304 808 if ( d->arch.hvm_domain.shared_page_va )
kaf24@9304 809 unmap_domain_page_global(
kaf24@9304 810 (void *)d->arch.hvm_domain.shared_page_va);
kaf24@9304 811
kaf24@9304 812 shadow_direct_map_clean(d);
kaf24@8708 813 }
kaf24@8708 814
kaf24@8708 815
kaf24@8708 816 void arch_svm_do_resume(struct vcpu *v)
kaf24@8708 817 {
kaf24@9061 818 /* pinning VCPU to a different core? */
kaf24@9061 819 if ( v->arch.hvm_svm.launch_core == smp_processor_id()) {
kaf24@9061 820 svm_do_resume( v );
kaf24@9061 821 reset_stack_and_jump( svm_asm_do_resume );
kaf24@9061 822 }
kaf24@9061 823 else {
kaf24@10534 824 if (svm_dbg_on)
kaf24@10534 825 printk("VCPU core pinned: %d to %d\n",
kaf24@9703 826 v->arch.hvm_svm.launch_core, smp_processor_id() );
kaf24@9061 827 v->arch.hvm_svm.launch_core = smp_processor_id();
kaf24@9061 828 svm_migrate_timers( v );
kaf24@9061 829 svm_do_resume( v );
kaf24@9061 830 reset_stack_and_jump( svm_asm_do_resume );
kaf24@9061 831 }
kaf24@9061 832 }
kaf24@9061 833
kaf24@9061 834
kaf24@9061 835 void svm_migrate_timers(struct vcpu *v)
kaf24@9061 836 {
kaf24@10182 837 struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
kaf24@10182 838
kaf24@10182 839 if ( pt->enabled ) {
kaf24@10182 840 migrate_timer( &pt->timer, v->processor );
kaf24@10182 841 migrate_timer( &v->arch.hvm_svm.hlt_timer, v->processor );
kaf24@10182 842 }
kaf24@9061 843 if ( hvm_apic_support(v->domain) && VLAPIC( v ))
kaf24@9061 844 migrate_timer( &(VLAPIC(v)->vlapic_timer ), v->processor );
kaf24@8708 845 }
kaf24@8708 846
kaf24@8708 847
kaf24@8708 848 static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
kaf24@8708 849 {
kaf24@8708 850 struct vcpu *v = current;
kaf24@8708 851 unsigned long eip;
kaf24@8708 852 unsigned long gpa; /* FIXME: PAE */
kaf24@8708 853 int result;
kaf24@8708 854 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 855
kaf24@8708 856 ASSERT(vmcb);
kaf24@8708 857
kaf24@8708 858 //#if HVM_DEBUG
kaf24@8708 859 eip = vmcb->rip;
kaf24@8708 860 HVM_DBG_LOG(DBG_LEVEL_VMMU,
kaf24@8708 861 "svm_do_page_fault = 0x%lx, eip = %lx, error_code = %lx",
kaf24@8708 862 va, eip, (unsigned long)regs->error_code);
kaf24@8708 863 //#endif
kaf24@8708 864
kaf24@8753 865 if ( !svm_paging_enabled(v) )
kaf24@8708 866 {
kaf24@8753 867 if ( shadow_direct_map_fault(va, regs) )
kaf24@8753 868 return 1;
kaf24@8753 869
kaf24@8708 870 handle_mmio(va, va);
kaf24@8708 871 return 1;
kaf24@8708 872 }
kaf24@8708 873
kaf24@8708 874
kaf24@8708 875 gpa = gva_to_gpa(va);
kaf24@8708 876
kaf24@8708 877 /* Use 1:1 page table to identify MMIO address space */
kaf24@8708 878 if (mmio_space(gpa))
kaf24@8708 879 {
kaf24@10289 880 /* No support for APIC */
kaf24@8708 881 if (!hvm_apic_support(v->domain) && gpa >= 0xFEC00000)
kaf24@8708 882 {
kaf24@9073 883 int inst_len;
kaf24@9073 884 inst_len = svm_instruction_length(v);
kaf24@9073 885 if (inst_len == -1)
kaf24@8708 886 {
kaf24@8708 887 printf("%s: INST_LEN - Unable to decode properly.\n", __func__);
kaf24@8708 888 domain_crash_synchronous();
kaf24@8708 889 }
kaf24@8708 890
kaf24@8708 891 __update_guest_eip(vmcb, inst_len);
kaf24@8708 892
kaf24@8708 893 return 1;
kaf24@8708 894 }
kaf24@8708 895
kaf24@8708 896 handle_mmio(va, gpa);
kaf24@8708 897
kaf24@8708 898 return 1;
kaf24@8708 899 }
kaf24@8708 900
kaf24@8708 901 result = shadow_fault(va, regs);
kaf24@8708 902
kaf24@8708 903 if( result ) {
kaf24@8708 904 /* Let's make sure that the Guest TLB is flushed */
kaf24@8708 905 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
kaf24@8708 906 }
kaf24@8708 907
kaf24@8708 908 return result;
kaf24@8708 909 }
kaf24@8708 910
kaf24@8708 911
kaf24@8708 912 static void svm_do_no_device_fault(struct vmcb_struct *vmcb)
kaf24@8708 913 {
kaf24@8708 914 struct vcpu *v = current;
kaf24@8708 915
kaf24@8708 916 setup_fpu(v);
kaf24@8852 917 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
kaf24@8852 918
kaf24@8852 919 if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) )
kaf24@8708 920 vmcb->cr0 &= ~X86_CR0_TS;
kaf24@8708 921 }
kaf24@8708 922
kaf24@8708 923
kaf24@8708 924 static void svm_do_general_protection_fault(struct vcpu *v,
kaf24@8708 925 struct cpu_user_regs *regs)
kaf24@8708 926 {
kaf24@8708 927 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 928 unsigned long eip, error_code;
kaf24@8708 929
kaf24@8708 930 ASSERT(vmcb);
kaf24@8708 931
kaf24@8708 932 eip = vmcb->rip;
kaf24@8708 933 error_code = vmcb->exitinfo1;
kaf24@8708 934
kaf24@9073 935 if (vmcb->idtr.limit == 0) {
kaf24@9073 936 printf("Huh? We got a GP Fault with an invalid IDTR!\n");
kaf24@9073 937 svm_dump_vmcb(__func__, vmcb);
kaf24@9073 938 svm_dump_regs(__func__, regs);
kaf24@9073 939 svm_dump_inst(vmcb->rip);
kaf24@9073 940 __hvm_bug(regs);
kaf24@9073 941 }
kaf24@9073 942
kaf24@8708 943 HVM_DBG_LOG(DBG_LEVEL_1,
kaf24@8708 944 "svm_general_protection_fault: eip = %lx, erro_code = %lx",
kaf24@8708 945 eip, error_code);
kaf24@8708 946
kaf24@8708 947 HVM_DBG_LOG(DBG_LEVEL_1,
kaf24@8708 948 "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
kaf24@8708 949 (unsigned long)regs->eax, (unsigned long)regs->ebx,
kaf24@8708 950 (unsigned long)regs->ecx, (unsigned long)regs->edx,
kaf24@8708 951 (unsigned long)regs->esi, (unsigned long)regs->edi);
kaf24@10084 952
kaf24@8708 953 /* Reflect it back into the guest */
kaf24@10082 954 svm_inject_exception(v, TRAP_gp_fault, 1, error_code);
kaf24@8708 955 }
kaf24@8708 956
kaf24@10222 957 /* Reserved bits ECX: [31:14], [12:4], [2:1]*/
kaf24@10222 958 #define SVM_VCPU_CPUID_L1_ECX_RESERVED 0xffffdff6
kaf24@10222 959 /* Reserved bits EDX: [31:29], [27], [22:20], [18], [10] */
kaf24@10222 960 #define SVM_VCPU_CPUID_L1_EDX_RESERVED 0xe8740400
kaf24@8708 961
kaf24@8708 962 static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
kaf24@8708 963 struct cpu_user_regs *regs)
kaf24@8708 964 {
kaf24@8708 965 unsigned int eax, ebx, ecx, edx;
kaf24@8708 966 unsigned long eip;
kaf24@8708 967 struct vcpu *v = current;
kaf24@9073 968 int inst_len;
kaf24@8708 969
kaf24@8708 970 ASSERT(vmcb);
kaf24@8708 971
kaf24@8708 972 eip = vmcb->rip;
kaf24@8708 973
kaf24@8708 974 HVM_DBG_LOG(DBG_LEVEL_1,
kaf24@8708 975 "do_cpuid: (eax) %lx, (ebx) %lx, (ecx) %lx, (edx) %lx,"
kaf24@8708 976 " (esi) %lx, (edi) %lx",
kaf24@8708 977 (unsigned long)regs->eax, (unsigned long)regs->ebx,
kaf24@8708 978 (unsigned long)regs->ecx, (unsigned long)regs->edx,
kaf24@8708 979 (unsigned long)regs->esi, (unsigned long)regs->edi);
kaf24@8708 980
kaf24@8708 981 cpuid(input, &eax, &ebx, &ecx, &edx);
kaf24@8708 982
kaf24@10222 983 if (input == 0x00000001)
kaf24@8708 984 {
kaf24@9416 985 if ( !hvm_apic_support(v->domain) ||
kaf24@8708 986 !vlapic_global_enabled((VLAPIC(v))) )
kaf24@9803 987 {
kaf24@10222 988 /* Since the apic is disabled, avoid any confusion
kfraser@10661 989 about SMP cpus being available */
kfraser@10661 990 clear_bit(X86_FEATURE_APIC, &edx);
kaf24@9803 991 }
kaf24@10222 992
kaf24@9062 993 #if CONFIG_PAGING_LEVELS < 3
kaf24@9062 994 clear_bit(X86_FEATURE_PAE, &edx);
kaf24@9062 995 clear_bit(X86_FEATURE_PSE, &edx);
kaf24@9062 996 clear_bit(X86_FEATURE_PSE36, &edx);
kaf24@9062 997 #else
kaf24@8708 998 if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
kaf24@8708 999 {
kaf24@9062 1000 if ( !v->domain->arch.hvm_domain.pae_enabled )
kfraser@10661 1001 clear_bit(X86_FEATURE_PAE, &edx);
kaf24@8708 1002 clear_bit(X86_FEATURE_PSE, &edx);
kaf24@8708 1003 clear_bit(X86_FEATURE_PSE36, &edx);
kaf24@8708 1004 }
kfraser@10661 1005 #endif
kaf24@8708 1006 /* Clear out reserved bits. */
kaf24@10222 1007 ecx &= ~SVM_VCPU_CPUID_L1_ECX_RESERVED;
kaf24@10222 1008 edx &= ~SVM_VCPU_CPUID_L1_EDX_RESERVED;
kaf24@10222 1009
kaf24@9062 1010 clear_bit(X86_FEATURE_MWAIT & 31, &ecx);
kaf24@10222 1011
kfraser@10661 1012 /* Guest should only see one logical processor.
kfraser@10661 1013 * See details on page 23 of AMD CPUID Specification.
kfraser@10661 1014 */
kfraser@10661 1015 clear_bit(X86_FEATURE_HT, &edx); /* clear the hyperthread bit */
kfraser@10661 1016 ebx &= 0xFF00FFFF; /* clear the logical processor count when HTT=0 */
kfraser@10661 1017 ebx |= 0x00010000; /* set to 1 just for precaution */
kfraser@10661 1018
kfraser@10661 1019 /* Disable machine check architecture */
kfraser@10661 1020 clear_bit(X86_FEATURE_MCA, &edx);
kfraser@10661 1021 clear_bit(X86_FEATURE_MCE, &edx);
kaf24@8708 1022 }
kfraser@10661 1023 else if ( (input > 0x00000005) && (input < 0x80000000) )
kaf24@10222 1024 {
kfraser@10661 1025 if ( !cpuid_hypervisor_leaves(input, &eax, &ebx, &ecx, &edx) )
kfraser@10661 1026 eax = ebx = ecx = edx = 0;
kaf24@10222 1027 }
kaf24@8708 1028 else if ( input == 0x80000001 )
kaf24@8708 1029 {
kfraser@10661 1030 /* We duplicate some CPUID_00000001 code because many bits of
kfraser@10661 1031 CPUID_80000001_EDX overlaps with CPUID_00000001_EDX. */
kaf24@10222 1032
kaf24@10222 1033 if ( !hvm_apic_support(v->domain) ||
kfraser@10661 1034 !vlapic_global_enabled((VLAPIC(v))) )
kaf24@10222 1035 {
kaf24@10222 1036 /* Since the apic is disabled, avoid any confusion
kfraser@10661 1037 about SMP cpus being available */
kfraser@10661 1038 clear_bit(X86_FEATURE_APIC, &edx);
kaf24@10222 1039 }
kaf24@10222 1040
kfraser@10661 1041 /* Clear the Cmp_Legacy bit
kfraser@10661 1042 * This bit is supposed to be zero when HTT = 0.
kfraser@10661 1043 * See details on page 23 of AMD CPUID Specification.
kfraser@10661 1044 */
kfraser@10661 1045 clear_bit(X86_FEATURE_CMP_LEGACY & 31, &ecx);
kaf24@10222 1046
kaf24@10222 1047 #ifdef __i386__
kaf24@8708 1048 /* Mask feature for Intel ia32e or AMD long mode. */
kaf24@10222 1049 clear_bit(X86_FEATURE_LAHF_LM & 31, &ecx);
kaf24@10222 1050
kaf24@8708 1051 clear_bit(X86_FEATURE_LM & 31, &edx);
kaf24@10222 1052 clear_bit(X86_FEATURE_SYSCALL & 31, &edx);
kaf24@10222 1053 #endif
kaf24@10222 1054
kaf24@10222 1055 #if CONFIG_PAGING_LEVELS < 3
kfraser@10661 1056 clear_bit(X86_FEATURE_NX & 31, &edx);
kaf24@10222 1057 clear_bit(X86_FEATURE_PAE, &edx);
kaf24@10222 1058 clear_bit(X86_FEATURE_PSE, &edx);
kaf24@10222 1059 clear_bit(X86_FEATURE_PSE36, &edx);
kaf24@10222 1060 #else
kaf24@10222 1061 if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
kaf24@10222 1062 {
kaf24@10222 1063 if ( !v->domain->arch.hvm_domain.pae_enabled )
kaf24@10222 1064 {
kfraser@10661 1065 clear_bit(X86_FEATURE_NX & 31, &edx);
kfraser@10661 1066 clear_bit(X86_FEATURE_PAE, &edx);
kaf24@10222 1067 }
kaf24@10222 1068 clear_bit(X86_FEATURE_PSE, &edx);
kaf24@10222 1069 clear_bit(X86_FEATURE_PSE36, &edx);
kaf24@10222 1070 }
kfraser@10661 1071 #endif
kaf24@10222 1072
kaf24@10222 1073 /* Make SVM feature invisible to the guest. */
kaf24@10222 1074 clear_bit(X86_FEATURE_SVME & 31, &ecx);
kfraser@10661 1075
kfraser@10661 1076 /* So far, we do not support 3DNow for the guest. */
kfraser@10661 1077 clear_bit(X86_FEATURE_3DNOW & 31, &edx);
kfraser@10661 1078 clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx);
kaf24@8708 1079 }
kaf24@10222 1080 else if ( ( input == 0x80000007 ) || ( input == 0x8000000A ) )
kaf24@10222 1081 {
kfraser@10661 1082 /* Mask out features of power management and SVM extension. */
kfraser@10661 1083 eax = ebx = ecx = edx = 0;
kaf24@10222 1084 }
kaf24@10222 1085 else if ( input == 0x80000008 )
kaf24@10222 1086 {
kfraser@10661 1087 ecx &= 0xFFFFFF00; /* Make sure Number of CPU core is 1 when HTT=0 */
kaf24@10222 1088 }
kaf24@8708 1089
kaf24@8708 1090 regs->eax = (unsigned long)eax;
kaf24@8708 1091 regs->ebx = (unsigned long)ebx;
kaf24@8708 1092 regs->ecx = (unsigned long)ecx;
kaf24@8708 1093 regs->edx = (unsigned long)edx;
kaf24@8708 1094
kaf24@8708 1095 HVM_DBG_LOG(DBG_LEVEL_1,
kaf24@8708 1096 "svm_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, "
kaf24@8708 1097 "ebx=%x, ecx=%x, edx=%x",
kaf24@8708 1098 eip, input, eax, ebx, ecx, edx);
kaf24@8708 1099
kaf24@8708 1100 inst_len = __get_instruction_length(vmcb, INSTR_CPUID, NULL);
kaf24@9073 1101 ASSERT(inst_len > 0);
kaf24@8708 1102 __update_guest_eip(vmcb, inst_len);
kaf24@8708 1103 }
kaf24@8708 1104
kaf24@8708 1105
kaf24@8708 1106 static inline unsigned long *get_reg_p(unsigned int gpreg,
kaf24@8708 1107 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
kaf24@8708 1108 {
kaf24@8708 1109 unsigned long *reg_p = NULL;
kaf24@8708 1110 switch (gpreg)
kaf24@8708 1111 {
kaf24@8708 1112 case SVM_REG_EAX:
kaf24@8708 1113 reg_p = (unsigned long *)&regs->eax;
kaf24@8708 1114 break;
kaf24@8708 1115 case SVM_REG_EBX:
kaf24@8708 1116 reg_p = (unsigned long *)&regs->ebx;
kaf24@8708 1117 break;
kaf24@8708 1118 case SVM_REG_ECX:
kaf24@8708 1119 reg_p = (unsigned long *)&regs->ecx;
kaf24@8708 1120 break;
kaf24@8708 1121 case SVM_REG_EDX:
kaf24@8708 1122 reg_p = (unsigned long *)&regs->edx;
kaf24@8708 1123 break;
kaf24@8708 1124 case SVM_REG_EDI:
kaf24@8708 1125 reg_p = (unsigned long *)&regs->edi;
kaf24@8708 1126 break;
kaf24@8708 1127 case SVM_REG_ESI:
kaf24@8708 1128 reg_p = (unsigned long *)&regs->esi;
kaf24@8708 1129 break;
kaf24@8708 1130 case SVM_REG_EBP:
kaf24@8708 1131 reg_p = (unsigned long *)&regs->ebp;
kaf24@8708 1132 break;
kaf24@8708 1133 case SVM_REG_ESP:
kaf24@8708 1134 reg_p = (unsigned long *)&vmcb->rsp;
kaf24@8708 1135 break;
kaf24@8708 1136 #if __x86_64__
kaf24@8708 1137 case SVM_REG_R8:
kaf24@8708 1138 reg_p = (unsigned long *)&regs->r8;
kaf24@8708 1139 break;
kaf24@8708 1140 case SVM_REG_R9:
kaf24@8708 1141 reg_p = (unsigned long *)&regs->r9;
kaf24@8708 1142 break;
kaf24@8708 1143 case SVM_REG_R10:
kaf24@8708 1144 reg_p = (unsigned long *)&regs->r10;
kaf24@8708 1145 break;
kaf24@8708 1146 case SVM_REG_R11:
kaf24@8708 1147 reg_p = (unsigned long *)&regs->r11;
kaf24@8708 1148 break;
kaf24@8708 1149 case SVM_REG_R12:
kaf24@8708 1150 reg_p = (unsigned long *)&regs->r12;
kaf24@8708 1151 break;
kaf24@8708 1152 case SVM_REG_R13:
kaf24@8708 1153 reg_p = (unsigned long *)&regs->r13;
kaf24@8708 1154 break;
kaf24@8708 1155 case SVM_REG_R14:
kaf24@8708 1156 reg_p = (unsigned long *)&regs->r14;
kaf24@8708 1157 break;
kaf24@8708 1158 case SVM_REG_R15:
kaf24@8708 1159 reg_p = (unsigned long *)&regs->r15;
kaf24@8708 1160 break;
kaf24@8708 1161 #endif
kaf24@8708 1162 default:
kaf24@8708 1163 BUG();
kaf24@8708 1164 }
kaf24@8708 1165
kaf24@8708 1166 return reg_p;
kaf24@8708 1167 }
kaf24@8708 1168
kaf24@8708 1169
kaf24@8708 1170 static inline unsigned long get_reg(unsigned int gpreg,
kaf24@8708 1171 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
kaf24@8708 1172 {
kaf24@8708 1173 unsigned long *gp;
kaf24@8708 1174 gp = get_reg_p(gpreg, regs, vmcb);
kaf24@8708 1175 return *gp;
kaf24@8708 1176 }
kaf24@8708 1177
kaf24@8708 1178
kaf24@8708 1179 static inline void set_reg(unsigned int gpreg, unsigned long value,
kaf24@8708 1180 struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
kaf24@8708 1181 {
kaf24@8708 1182 unsigned long *gp;
kaf24@8708 1183 gp = get_reg_p(gpreg, regs, vmcb);
kaf24@8708 1184 *gp = value;
kaf24@8708 1185 }
kaf24@8708 1186
kaf24@8708 1187
kaf24@8708 1188 static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
kaf24@8708 1189 struct cpu_user_regs *regs)
kaf24@8708 1190 {
kaf24@8708 1191 unsigned long *reg_p = 0;
kaf24@8708 1192 unsigned int gpreg = 0;
kaf24@8708 1193 unsigned long eip;
kaf24@9073 1194 int inst_len;
kaf24@9073 1195 int index;
kaf24@8708 1196 struct vmcb_struct *vmcb;
kaf24@8708 1197 u8 buffer[MAX_INST_LEN];
kaf24@9073 1198 u8 prefix = 0;
kaf24@8708 1199
kaf24@8708 1200 vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 1201
kaf24@8708 1202 ASSERT(vmcb);
kaf24@8708 1203
kaf24@8708 1204 eip = vmcb->rip;
kaf24@8708 1205 inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
kaf24@9073 1206 index = skip_prefix_bytes(buffer, sizeof(buffer));
kaf24@9073 1207
kaf24@9073 1208 ASSERT(buffer[index+0] == 0x0f && (buffer[index+1] & 0xFD) == 0x21);
kaf24@9073 1209
kaf24@9073 1210 if (index > 0 && (buffer[index-1] & 0xF0) == 0x40)
kaf24@9073 1211 prefix = buffer[index-1];
kaf24@9073 1212
kaf24@9073 1213 gpreg = decode_src_reg(prefix, buffer[index + 2]);
kaf24@9073 1214 ASSERT(reg == decode_dest_reg(prefix, buffer[index + 2]));
kaf24@8708 1215
kaf24@8708 1216 HVM_DBG_LOG(DBG_LEVEL_1, "svm_dr_access : eip=%lx, reg=%d, gpreg = %x",
kaf24@8708 1217 eip, reg, gpreg);
kaf24@8708 1218
kaf24@8708 1219 reg_p = get_reg_p(gpreg, regs, vmcb);
kaf24@8708 1220
kaf24@8708 1221 switch (type)
kaf24@8708 1222 {
kaf24@8708 1223 case TYPE_MOV_TO_DR:
kaf24@8708 1224 inst_len = __get_instruction_length(vmcb, INSTR_MOV2DR, buffer);
kaf24@8708 1225 v->arch.guest_context.debugreg[reg] = *reg_p;
kaf24@8708 1226 break;
kaf24@8708 1227 case TYPE_MOV_FROM_DR:
kaf24@8708 1228 inst_len = __get_instruction_length(vmcb, INSTR_MOVDR2, buffer);
kaf24@8708 1229 *reg_p = v->arch.guest_context.debugreg[reg];
kaf24@8708 1230 break;
kaf24@8708 1231 default:
kaf24@8708 1232 __hvm_bug(regs);
kaf24@8708 1233 break;
kaf24@8708 1234 }
kaf24@9073 1235 ASSERT(inst_len > 0);
kaf24@8708 1236 __update_guest_eip(vmcb, inst_len);
kaf24@8708 1237 }
kaf24@8708 1238
kaf24@8708 1239
kfraser@10661 1240 static void svm_get_prefix_info(
kfraser@10661 1241 struct vmcb_struct *vmcb,
kfraser@10661 1242 unsigned int dir, segment_selector_t **seg, unsigned int *asize)
kaf24@8708 1243 {
kaf24@8708 1244 unsigned char inst[MAX_INST_LEN];
kaf24@8708 1245 int i;
kaf24@8708 1246
kaf24@8708 1247 memset(inst, 0, MAX_INST_LEN);
kaf24@8708 1248 if (inst_copy_from_guest(inst, svm_rip2pointer(vmcb), sizeof(inst))
kaf24@8708 1249 != MAX_INST_LEN)
kaf24@8708 1250 {
kaf24@10080 1251 printk("%s: get guest instruction failed\n", __func__);
kaf24@8708 1252 domain_crash_synchronous();
kaf24@8708 1253 }
kaf24@8708 1254
kaf24@8708 1255 for (i = 0; i < MAX_INST_LEN; i++)
kaf24@8708 1256 {
kaf24@8708 1257 switch (inst[i])
kaf24@8708 1258 {
kaf24@8708 1259 case 0xf3: /* REPZ */
kaf24@8708 1260 case 0xf2: /* REPNZ */
kaf24@8708 1261 case 0xf0: /* LOCK */
kaf24@8708 1262 case 0x66: /* data32 */
kaf24@8708 1263 #if __x86_64__
kaf24@8708 1264 /* REX prefixes */
kaf24@8708 1265 case 0x40:
kaf24@8708 1266 case 0x41:
kaf24@8708 1267 case 0x42:
kaf24@8708 1268 case 0x43:
kaf24@8708 1269 case 0x44:
kaf24@8708 1270 case 0x45:
kaf24@8708 1271 case 0x46:
kaf24@8708 1272 case 0x47:
kaf24@8708 1273
kaf24@8708 1274 case 0x48:
kaf24@8708 1275 case 0x49:
kaf24@8708 1276 case 0x4a:
kaf24@8708 1277 case 0x4b:
kaf24@8708 1278 case 0x4c:
kaf24@8708 1279 case 0x4d:
kaf24@8708 1280 case 0x4e:
kaf24@8708 1281 case 0x4f:
kaf24@8708 1282 #endif
kaf24@8708 1283 continue;
kaf24@10080 1284 case 0x67: /* addr32 */
kaf24@10080 1285 *asize ^= 48; /* Switch 16/32 bits */
kaf24@10080 1286 continue;
kaf24@8708 1287 case 0x2e: /* CS */
kaf24@10080 1288 *seg = &vmcb->cs;
kaf24@10080 1289 continue;
kaf24@8708 1290 case 0x36: /* SS */
kaf24@10080 1291 *seg = &vmcb->ss;
kaf24@10080 1292 continue;
kaf24@8708 1293 case 0x26: /* ES */
kaf24@10080 1294 *seg = &vmcb->es;
kaf24@10080 1295 continue;
kaf24@8708 1296 case 0x64: /* FS */
kaf24@10080 1297 *seg = &vmcb->fs;
kaf24@10080 1298 continue;
kaf24@8708 1299 case 0x65: /* GS */
kaf24@10080 1300 *seg = &vmcb->gs;
kaf24@10080 1301 continue;
kaf24@8708 1302 case 0x3e: /* DS */
kaf24@10080 1303 *seg = &vmcb->ds;
kaf24@10080 1304 continue;
kaf24@8708 1305 default:
kaf24@10080 1306 break;
kaf24@8708 1307 }
kaf24@10080 1308 return;
kaf24@8708 1309 }
kaf24@8708 1310 }
kaf24@8708 1311
kaf24@8708 1312
kaf24@8708 1313 /* Get the address of INS/OUTS instruction */
kfraser@10661 1314 static inline int svm_get_io_address(
kfraser@10661 1315 struct vcpu *v,
kfraser@10661 1316 struct cpu_user_regs *regs, unsigned int dir,
kfraser@10661 1317 unsigned long *count, unsigned long *addr)
kaf24@8708 1318 {
kaf24@10080 1319 unsigned long reg;
kaf24@10080 1320 unsigned int asize = 0;
kaf24@10080 1321 unsigned int isize;
kaf24@10080 1322 int long_mode;
kaf24@10080 1323 ioio_info_t info;
kaf24@10080 1324 segment_selector_t *seg = NULL;
kaf24@10082 1325 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@10080 1326
kaf24@10080 1327 info.bytes = vmcb->exitinfo1;
kaf24@10080 1328
kaf24@10080 1329 /* If we're in long mode, we shouldn't check the segment presence and limit */
kaf24@10080 1330 long_mode = vmcb->cs.attributes.fields.l && vmcb->efer & EFER_LMA;
kaf24@10080 1331
kaf24@10080 1332 /* d field of cs.attributes is 1 for 32-bit, 0 for 16 or 64 bit.
kaf24@10080 1333 * l field combined with EFER_LMA -> longmode says whether it's 16 or 64 bit.
kaf24@10080 1334 */
kaf24@10080 1335 asize = (long_mode)?64:((vmcb->cs.attributes.fields.db)?32:16);
kaf24@10080 1336
kaf24@10080 1337
kaf24@10080 1338 /* The ins/outs instructions are single byte, so if we have got more
kaf24@10080 1339 * than one byte (+ maybe rep-prefix), we have some prefix so we need
kaf24@10080 1340 * to figure out what it is...
kaf24@10080 1341 */
kaf24@10080 1342 isize = vmcb->exitinfo2 - vmcb->rip;
kaf24@10080 1343
kaf24@10080 1344 if (info.fields.rep)
kaf24@10080 1345 isize --;
kaf24@10080 1346
kaf24@10080 1347 if (isize > 1)
kaf24@10080 1348 {
kaf24@10080 1349 svm_get_prefix_info(vmcb, dir, &seg, &asize);
kaf24@10080 1350 }
kaf24@10080 1351
kaf24@10080 1352 ASSERT(dir == IOREQ_READ || dir == IOREQ_WRITE);
kaf24@8708 1353
kaf24@8708 1354 if (dir == IOREQ_WRITE)
kaf24@8708 1355 {
kaf24@10080 1356 reg = regs->esi;
kaf24@10080 1357 if (!seg) /* If no prefix, used DS. */
kaf24@10080 1358 seg = &vmcb->ds;
kaf24@8708 1359 }
kaf24@8708 1360 else
kaf24@8708 1361 {
kaf24@10080 1362 reg = regs->edi;
kaf24@10080 1363 seg = &vmcb->es; /* Note: This is ALWAYS ES. */
kaf24@8708 1364 }
kaf24@8708 1365
kaf24@10080 1366 /* If the segment isn't present, give GP fault! */
kaf24@10080 1367 if (!long_mode && !seg->attributes.fields.p)
kaf24@10080 1368 {
kaf24@10082 1369 svm_inject_exception(v, TRAP_gp_fault, 1, seg->sel);
kaf24@10080 1370 return 0;
kaf24@10080 1371 }
kaf24@10080 1372
kaf24@10080 1373 if (asize == 16)
kaf24@10080 1374 {
kaf24@10080 1375 *addr = (reg & 0xFFFF);
kaf24@10080 1376 *count = regs->ecx & 0xffff;
kaf24@10080 1377 }
kaf24@10080 1378 else
kaf24@10080 1379 {
kaf24@10080 1380 *addr = reg;
kaf24@10080 1381 *count = regs->ecx;
kaf24@10080 1382 }
kaf24@10080 1383
kaf24@10080 1384 if (!long_mode) {
kaf24@10080 1385 if (*addr > seg->limit)
kaf24@10080 1386 {
kaf24@10082 1387 svm_inject_exception(v, TRAP_gp_fault, 1, seg->sel);
kaf24@10080 1388 return 0;
kaf24@10080 1389 }
kaf24@10080 1390 else
kaf24@10080 1391 {
kaf24@10080 1392 *addr += seg->base;
kaf24@10080 1393 }
kaf24@10080 1394 }
kaf24@10080 1395
kaf24@10080 1396
kaf24@10080 1397 return 1;
kaf24@8708 1398 }
kaf24@8708 1399
kaf24@8708 1400
kaf24@10763 1401 static void svm_io_instruction(struct vcpu *v)
kaf24@8708 1402 {
kaf24@10763 1403 struct cpu_user_regs *regs;
kaf24@10763 1404 struct hvm_io_op *pio_opp;
kaf24@10080 1405 unsigned int port;
kaf24@10080 1406 unsigned int size, dir;
kaf24@8708 1407 ioio_info_t info;
kaf24@8708 1408 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 1409
kaf24@8708 1410 ASSERT(vmcb);
kaf24@10763 1411 pio_opp = &current->arch.hvm_vcpu.io_op;
kaf24@10763 1412 pio_opp->instr = INSTR_PIO;
kaf24@10763 1413 pio_opp->flags = 0;
kaf24@10763 1414
kaf24@10763 1415 regs = &pio_opp->io_context;
kaf24@10763 1416
kaf24@10763 1417 /* Copy current guest state into io instruction state structure. */
kaf24@10763 1418 memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
kaf24@8708 1419
kaf24@8708 1420 info.bytes = vmcb->exitinfo1;
kaf24@8708 1421
kaf24@8708 1422 port = info.fields.port; /* port used to be addr */
kaf24@8708 1423 dir = info.fields.type; /* direction */
kaf24@8708 1424 if (info.fields.sz32)
kaf24@8708 1425 size = 4;
kaf24@8708 1426 else if (info.fields.sz16)
kaf24@8708 1427 size = 2;
kaf24@8708 1428 else
kaf24@8708 1429 size = 1;
kaf24@8708 1430
kaf24@8708 1431 HVM_DBG_LOG(DBG_LEVEL_IO,
kaf24@10085 1432 "svm_io_instruction: port 0x%x eip=%x:%"PRIx64", "
kaf24@10085 1433 "exit_qualification = %"PRIx64,
kaf24@10085 1434 port, vmcb->cs.sel, vmcb->rip, info.bytes);
kaf24@10085 1435
kaf24@8708 1436 /* string instruction */
kaf24@8708 1437 if (info.fields.str)
kaf24@8708 1438 {
kaf24@10080 1439 unsigned long addr, count;
kaf24@8708 1440 int sign = regs->eflags & EF_DF ? -1 : 1;
kaf24@8708 1441
kaf24@10082 1442 if (!svm_get_io_address(v, regs, dir, &count, &addr))
kaf24@10080 1443 {
kaf24@10085 1444 /* We failed to get a valid address, so don't do the IO operation -
kaf24@10080 1445 * it would just get worse if we do! Hopefully the guest is handing
kaf24@10080 1446 * gp-faults...
kaf24@10080 1447 */
kaf24@10080 1448 return;
kaf24@10080 1449 }
kaf24@8708 1450
kaf24@8708 1451 /* "rep" prefix */
kaf24@8708 1452 if (info.fields.rep)
kaf24@8708 1453 {
kaf24@10763 1454 pio_opp->flags |= REPZ;
kaf24@10080 1455 }
kaf24@10080 1456 else
kaf24@10080 1457 {
kaf24@10080 1458 count = 1;
kaf24@8708 1459 }
kaf24@8708 1460
kaf24@8708 1461 /*
kaf24@8708 1462 * Handle string pio instructions that cross pages or that
kaf24@8708 1463 * are unaligned. See the comments in hvm_platform.c/handle_mmio()
kaf24@8708 1464 */
kaf24@8708 1465 if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK))
kaf24@8708 1466 {
kaf24@8708 1467 unsigned long value = 0;
kaf24@8708 1468
kaf24@10763 1469 pio_opp->flags |= OVERLAP;
kaf24@8708 1470
kaf24@8708 1471 if (dir == IOREQ_WRITE)
kaf24@8708 1472 hvm_copy(&value, addr, size, HVM_COPY_IN);
kaf24@8708 1473
kaf24@8708 1474 send_pio_req(regs, port, 1, size, value, dir, 0);
kaf24@8708 1475 }
kaf24@8708 1476 else
kaf24@8708 1477 {
kaf24@8708 1478 if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK))
kaf24@8708 1479 {
kaf24@8708 1480 if (sign > 0)
kaf24@8708 1481 count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
kaf24@8708 1482 else
kaf24@8708 1483 count = (addr & ~PAGE_MASK) / size;
kaf24@8708 1484 }
kaf24@9471 1485 else
kaf24@9471 1486 vmcb->rip = vmcb->exitinfo2;
kaf24@8708 1487
kaf24@8708 1488 send_pio_req(regs, port, count, size, addr, dir, 1);
kaf24@8708 1489 }
kaf24@8708 1490 }
kaf24@8708 1491 else
kaf24@8708 1492 {
kaf24@9382 1493 /*
kaf24@9382 1494 * On SVM, the RIP of the intruction following the IN/OUT is saved in
kaf24@9382 1495 * ExitInfo2
kaf24@9382 1496 */
kaf24@9382 1497 vmcb->rip = vmcb->exitinfo2;
kaf24@9382 1498
kaf24@8708 1499 if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
kaf24@8708 1500 hvm_print_line(v, regs->eax); /* guest debug output */
kaf24@8708 1501
kaf24@8708 1502 send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
kaf24@8708 1503 }
kaf24@8708 1504 }
kaf24@8708 1505
kaf24@8708 1506 static int svm_set_cr0(unsigned long value)
kaf24@8708 1507 {
kaf24@8708 1508 struct vcpu *v = current;
kaf24@8708 1509 unsigned long mfn;
kaf24@8708 1510 int paging_enabled;
kaf24@8708 1511 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@9703 1512
kaf24@8708 1513 ASSERT(vmcb);
kaf24@8708 1514
kaf24@8708 1515 /* We don't want to lose PG. ET is reserved and should be always be 1*/
kaf24@8708 1516 paging_enabled = svm_paging_enabled(v);
kaf24@8708 1517 value |= X86_CR0_ET;
kaf24@8708 1518 vmcb->cr0 = value | X86_CR0_PG;
kaf24@8708 1519 v->arch.hvm_svm.cpu_shadow_cr0 = value;
kaf24@8708 1520
kaf24@8852 1521 /* TS cleared? Then initialise FPU now. */
kaf24@8852 1522 if ( !(value & X86_CR0_TS) )
kaf24@8852 1523 {
kaf24@8852 1524 setup_fpu(v);
kaf24@8852 1525 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
kaf24@8708 1526 }
kaf24@8708 1527
kaf24@8708 1528 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
kaf24@8708 1529
kaf24@8708 1530 if ((value & X86_CR0_PE) && (value & X86_CR0_PG) && !paging_enabled)
kaf24@8708 1531 {
kaf24@8708 1532 /* The guest CR3 must be pointing to the guest physical. */
kaf24@8708 1533 if (!VALID_MFN(mfn =
kaf24@8736 1534 get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT))
kaf24@8726 1535 || !get_page(mfn_to_page(mfn), v->domain))
kaf24@8708 1536 {
kaf24@8708 1537 printk("Invalid CR3 value = %lx\n", v->arch.hvm_svm.cpu_cr3);
kaf24@8708 1538 domain_crash_synchronous(); /* need to take a clean path */
kaf24@8708 1539 }
kaf24@8708 1540
kaf24@8708 1541 #if defined(__x86_64__)
kaf24@8708 1542 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state)
kaf24@8708 1543 && !test_bit(SVM_CPU_STATE_PAE_ENABLED,
kaf24@8708 1544 &v->arch.hvm_svm.cpu_state))
kaf24@8708 1545 {
kaf24@8708 1546 HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n");
kaf24@10082 1547 svm_inject_exception(v, TRAP_gp_fault, 1, 0);
kaf24@8708 1548 }
kaf24@8708 1549
kaf24@8708 1550 if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state))
kaf24@8708 1551 {
kaf24@8708 1552 /* Here the PAE is should to be opened */
kaf24@8708 1553 HVM_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n");
kaf24@8708 1554 set_bit(SVM_CPU_STATE_LMA_ENABLED,
kaf24@8708 1555 &v->arch.hvm_svm.cpu_state);
kaf24@9063 1556 vmcb->efer |= (EFER_LMA | EFER_LME);
kaf24@9703 1557 if (!shadow_set_guest_paging_levels(v->domain, PAGING_L4) )
kaf24@8708 1558 {
kaf24@8708 1559 printk("Unsupported guest paging levels\n");
kaf24@8708 1560 domain_crash_synchronous(); /* need to take a clean path */
kaf24@8708 1561 }
kaf24@8708 1562 }
kaf24@8708 1563 else
kaf24@9063 1564 #endif /* __x86_64__ */
kaf24@8708 1565 {
kaf24@9063 1566 #if CONFIG_PAGING_LEVELS >= 3
kaf24@9703 1567 /* seems it's a 32-bit or 32-bit PAE guest */
kaf24@9703 1568 if ( test_bit(SVM_CPU_STATE_PAE_ENABLED,
kaf24@9703 1569 &v->arch.hvm_svm.cpu_state) )
kaf24@8708 1570 {
kaf24@9703 1571 /* The guest enables PAE first and then it enables PG, it is
kaf24@9703 1572 * really a PAE guest */
kaf24@9703 1573 if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L3) )
kaf24@9703 1574 {
kaf24@9703 1575 printk("Unsupported guest paging levels\n");
kaf24@9703 1576 domain_crash_synchronous();
kaf24@9703 1577 }
kaf24@9703 1578 }
kaf24@9703 1579 else
kaf24@9703 1580 {
kaf24@9703 1581 if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L2) )
kaf24@9703 1582 {
kaf24@9703 1583 printk("Unsupported guest paging levels\n");
kaf24@9703 1584 domain_crash_synchronous(); /* need to take a clean path */
kaf24@9703 1585 }
kaf24@8708 1586 }
kaf24@8708 1587 #endif
kaf24@8708 1588 }
kaf24@8708 1589
kaf24@8708 1590 /* Now arch.guest_table points to machine physical. */
kaf24@10289 1591 v->arch.guest_table = pagetable_from_pfn(mfn);
kaf24@8708 1592 update_pagetables(v);
kaf24@8708 1593
kaf24@8708 1594 HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
kaf24@8708 1595 (unsigned long) (mfn << PAGE_SHIFT));
kaf24@8708 1596
kaf24@8708 1597 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
kaf24@8708 1598 vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
kaf24@8708 1599
kaf24@8708 1600 /* arch->shadow_table should hold the next CR3 for shadow */
kaf24@8708 1601 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx\n",
kaf24@8708 1602 v->arch.hvm_svm.cpu_cr3, mfn);
kaf24@9703 1603
kaf24@9703 1604 return 1;
kaf24@8708 1605 }
kaf24@8708 1606
kaf24@9703 1607 if ( !((value & X86_CR0_PE) && (value & X86_CR0_PG)) && paging_enabled )
kaf24@9703 1608 if ( v->arch.hvm_svm.cpu_cr3 ) {
kaf24@9703 1609 put_page(mfn_to_page(get_mfn_from_gpfn(
kaf24@9703 1610 v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT)));
kaf24@10289 1611 v->arch.guest_table = pagetable_null();
kaf24@9703 1612 }
kaf24@9703 1613
kaf24@8708 1614 /*
kaf24@8708 1615 * SVM implements paged real-mode and when we return to real-mode
kaf24@8708 1616 * we revert back to the physical mappings that the domain builder
kaf24@8708 1617 * created.
kaf24@8708 1618 */
kaf24@8708 1619 if ((value & X86_CR0_PE) == 0) {
kaf24@10289 1620 if (value & X86_CR0_PG) {
kaf24@10082 1621 svm_inject_exception(v, TRAP_gp_fault, 1, 0);
kaf24@8893 1622 return 0;
kaf24@8893 1623 }
kaf24@8708 1624
kaf24@9703 1625 clear_all_shadow_status( v->domain );
kaf24@9703 1626 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
kaf24@9703 1627 vmcb->cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
kaf24@9703 1628 }
kaf24@9703 1629 else if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE )
kaf24@9703 1630 {
kaf24@9703 1631 /* we should take care of this kind of situation */
kaf24@9703 1632 clear_all_shadow_status(v->domain);
kaf24@8708 1633 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
kaf24@8708 1634 vmcb->cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
kaf24@8708 1635 }
kaf24@8708 1636
kaf24@8708 1637 return 1;
kaf24@8708 1638 }
kaf24@8708 1639
kaf24@8708 1640 /*
kaf24@8708 1641 * Read from control registers. CR0 and CR4 are read from the shadow.
kaf24@8708 1642 */
kaf24@8708 1643 static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
kaf24@8708 1644 {
kaf24@8708 1645 unsigned long value = 0;
kaf24@8708 1646 struct vcpu *v = current;
kaf24@8708 1647 struct vmcb_struct *vmcb;
kaf24@8708 1648
kaf24@8708 1649 vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 1650 ASSERT(vmcb);
kaf24@8708 1651
kaf24@8708 1652 switch (cr)
kaf24@8708 1653 {
kaf24@8708 1654 case 0:
kaf24@8708 1655 value = v->arch.hvm_svm.cpu_shadow_cr0;
kaf24@9703 1656 if (svm_dbg_on)
kaf24@9703 1657 printk("CR0 read =%lx \n", value );
kaf24@9703 1658 break;
kaf24@8708 1659 case 2:
kaf24@8708 1660 value = vmcb->cr2;
kaf24@8708 1661 break;
kaf24@8708 1662 case 3:
kaf24@8708 1663 value = (unsigned long) v->arch.hvm_svm.cpu_cr3;
kaf24@9703 1664 if (svm_dbg_on)
kaf24@9703 1665 printk("CR3 read =%lx \n", value );
kaf24@9703 1666 break;
kaf24@8708 1667 case 4:
kaf24@9073 1668 value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr4;
kaf24@9703 1669 if (svm_dbg_on)
kaf24@9703 1670 printk( "CR4 read=%lx\n", value );
kaf24@8708 1671 break;
kaf24@8708 1672 case 8:
kaf24@8708 1673 #if 0
kaf24@8708 1674 value = vmcb->m_cr8;
kaf24@8708 1675 #else
kaf24@8708 1676 ASSERT(0);
kaf24@8708 1677 #endif
kaf24@8708 1678 break;
kaf24@8708 1679
kaf24@8708 1680 default:
kaf24@8708 1681 __hvm_bug(regs);
kaf24@8708 1682 }
kaf24@8708 1683
kaf24@8708 1684 set_reg(gp, value, regs, vmcb);
kaf24@8708 1685
kaf24@8708 1686 HVM_DBG_LOG(DBG_LEVEL_VMMU, "mov_from_cr: CR%d, value = %lx,", cr, value);
kaf24@8708 1687 }
kaf24@8708 1688
kaf24@8708 1689
kaf24@9703 1690 static inline int svm_pgbit_test(struct vcpu *v)
kaf24@9703 1691 {
kaf24@9703 1692 return v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_PG;
kaf24@9703 1693 }
kaf24@9703 1694
kaf24@9703 1695
kaf24@8708 1696 /*
kaf24@8708 1697 * Write to control registers
kaf24@8708 1698 */
kaf24@8708 1699 static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
kaf24@8708 1700 {
kaf24@8708 1701 unsigned long value;
kaf24@8708 1702 unsigned long old_cr;
kaf24@8708 1703 struct vcpu *v = current;
kaf24@8708 1704 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 1705
kaf24@8708 1706 ASSERT(vmcb);
kaf24@8708 1707
kaf24@8708 1708 value = get_reg(gpreg, regs, vmcb);
kaf24@8708 1709
kaf24@8708 1710 HVM_DBG_LOG(DBG_LEVEL_1, "mov_to_cr: CR%d, value = %lx,", cr, value);
kaf24@8708 1711 HVM_DBG_LOG(DBG_LEVEL_1, "current = %lx,", (unsigned long) current);
kaf24@8708 1712
kaf24@8708 1713 switch (cr)
kaf24@8708 1714 {
kaf24@8708 1715 case 0:
kaf24@9703 1716 if (svm_dbg_on)
kaf24@9703 1717 printk("CR0 write =%lx \n", value );
kaf24@8708 1718 return svm_set_cr0(value);
kaf24@8708 1719
kaf24@8708 1720 case 3:
kaf24@8708 1721 {
kaf24@8708 1722 unsigned long old_base_mfn, mfn;
kaf24@9703 1723 if (svm_dbg_on)
kaf24@9703 1724 printk("CR3 write =%lx \n", value );
kaf24@8708 1725 /* If paging is not enabled yet, simply copy the value to CR3. */
kaf24@8708 1726 if (!svm_paging_enabled(v)) {
kaf24@8708 1727 v->arch.hvm_svm.cpu_cr3 = value;
kaf24@8708 1728 break;
kaf24@8708 1729 }
kaf24@8708 1730 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
kaf24@8708 1731
kaf24@8708 1732 /* We make a new one if the shadow does not exist. */
kaf24@8708 1733 if (value == v->arch.hvm_svm.cpu_cr3)
kaf24@8708 1734 {
kaf24@8708 1735 /*
kaf24@8708 1736 * This is simple TLB flush, implying the guest has
kaf24@8708 1737 * removed some translation or changed page attributes.
kaf24@8708 1738 * We simply invalidate the shadow.
kaf24@8708 1739 */
kaf24@8736 1740 mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
kaf24@8708 1741 if (mfn != pagetable_get_pfn(v->arch.guest_table))
kaf24@8708 1742 __hvm_bug(regs);
kaf24@8708 1743 shadow_sync_all(v->domain);
kaf24@8708 1744 }
kaf24@8708 1745 else
kaf24@8708 1746 {
kaf24@8708 1747 /*
kaf24@8708 1748 * If different, make a shadow. Check if the PDBR is valid
kaf24@8708 1749 * first.
kaf24@8708 1750 */
kaf24@8708 1751 HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
kaf24@8708 1752 if (((value >> PAGE_SHIFT) > v->domain->max_pages)
kaf24@8736 1753 || !VALID_MFN(mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT))
kaf24@8726 1754 || !get_page(mfn_to_page(mfn), v->domain))
kaf24@8708 1755 {
kaf24@8708 1756 printk("Invalid CR3 value=%lx\n", value);
kaf24@8708 1757 domain_crash_synchronous(); /* need to take a clean path */
kaf24@8708 1758 }
kaf24@8708 1759
kaf24@8708 1760 old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
kaf24@10289 1761 v->arch.guest_table = pagetable_from_pfn(mfn);
kaf24@8708 1762
kaf24@8708 1763 if (old_base_mfn)
kaf24@8726 1764 put_page(mfn_to_page(old_base_mfn));
kaf24@8708 1765
kaf24@9703 1766 /*
kaf24@9703 1767 * arch.shadow_table should now hold the next CR3 for shadow
kaf24@9703 1768 */
kaf24@9703 1769 #if CONFIG_PAGING_LEVELS >= 3
kaf24@9703 1770 if ( v->domain->arch.ops->guest_paging_levels == PAGING_L3 )
kaf24@9703 1771 shadow_sync_all(v->domain);
kaf24@9703 1772 #endif
kaf24@9703 1773 v->arch.hvm_svm.cpu_cr3 = value;
kaf24@8708 1774 update_pagetables(v);
kaf24@8708 1775 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value);
kaf24@8708 1776 vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
kaf24@8708 1777 }
kaf24@8708 1778 break;
kaf24@8708 1779 }
kaf24@8708 1780
kaf24@9703 1781 case 4: /* CR4 */
kaf24@9703 1782 {
kaf24@9703 1783 if (svm_dbg_on)
kaf24@9703 1784 printk( "write cr4=%lx, cr0=%lx\n",
kaf24@9703 1785 value, v->arch.hvm_svm.cpu_shadow_cr0 );
kaf24@9703 1786 old_cr = v->arch.hvm_svm.cpu_shadow_cr4;
kaf24@9703 1787 if ( value & X86_CR4_PAE && !(old_cr & X86_CR4_PAE) )
kaf24@9703 1788 {
kaf24@9703 1789 set_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
kaf24@9703 1790 if ( svm_pgbit_test(v) )
kaf24@9703 1791 {
kaf24@9703 1792 /* The guest is a 32-bit PAE guest. */
kfraser@10798 1793 #if CONFIG_PAGING_LEVELS >= 3
kaf24@9703 1794 unsigned long mfn, old_base_mfn;
kaf24@9703 1795
kaf24@9703 1796 if( !shadow_set_guest_paging_levels(v->domain, PAGING_L3) )
kaf24@9703 1797 {
kaf24@9703 1798 printk("Unsupported guest paging levels\n");
kaf24@9703 1799 domain_crash_synchronous(); /* need to take a clean path */
kaf24@9703 1800 }
kaf24@9703 1801
kaf24@9703 1802 if ( !VALID_MFN(mfn = get_mfn_from_gpfn(
kaf24@9703 1803 v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT)) ||
kaf24@9703 1804 !get_page(mfn_to_page(mfn), v->domain) )
kaf24@9703 1805 {
kaf24@9703 1806 printk("Invalid CR3 value = %lx", v->arch.hvm_svm.cpu_cr3);
kaf24@9703 1807 domain_crash_synchronous(); /* need to take a clean path */
kaf24@9703 1808 }
kaf24@9703 1809
kaf24@9703 1810 old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
kaf24@9703 1811 if ( old_base_mfn )
kaf24@9703 1812 put_page(mfn_to_page(old_base_mfn));
kaf24@9703 1813
kaf24@9703 1814 /*
kaf24@9703 1815 * Now arch.guest_table points to machine physical.
kaf24@9703 1816 */
kaf24@9703 1817
kaf24@10289 1818 v->arch.guest_table = pagetable_from_pfn(mfn);
kaf24@9703 1819 update_pagetables(v);
kaf24@9703 1820
kaf24@9703 1821 HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
kaf24@9703 1822 (unsigned long) (mfn << PAGE_SHIFT));
kaf24@9703 1823
kaf24@9703 1824 vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
kaf24@9703 1825
kaf24@9703 1826 /*
kaf24@9703 1827 * arch->shadow_table should hold the next CR3 for shadow
kaf24@9703 1828 */
kaf24@9703 1829
kaf24@9703 1830 HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx",
kaf24@9703 1831 v->arch.hvm_svm.cpu_cr3, mfn);
kaf24@9703 1832 #endif
kaf24@9703 1833 }
kaf24@9703 1834 else
kaf24@9703 1835 {
kaf24@9703 1836 /* The guest is a 64 bit or 32-bit PAE guest. */
kfraser@10798 1837 #if CONFIG_PAGING_LEVELS >= 3
kaf24@9703 1838 if ( (v->domain->arch.ops != NULL) &&
kaf24@9703 1839 v->domain->arch.ops->guest_paging_levels == PAGING_L2)
kaf24@9703 1840 {
kaf24@9703 1841 /* Seems the guest first enables PAE without enabling PG,
kaf24@9703 1842 * it must enable PG after that, and it is a 32-bit PAE
kaf24@9703 1843 * guest */
kaf24@9703 1844
kaf24@9703 1845 if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L3) )
kaf24@9703 1846 {
kaf24@9703 1847 printk("Unsupported guest paging levels\n");
kaf24@9703 1848 domain_crash_synchronous();
kaf24@9703 1849 }
kaf24@9703 1850 }
kaf24@9703 1851 else
kaf24@9703 1852 {
kaf24@9703 1853 if ( !shadow_set_guest_paging_levels(v->domain,
kaf24@9703 1854 PAGING_L4) )
kaf24@9703 1855 {
kaf24@9703 1856 printk("Unsupported guest paging levels\n");
kaf24@9703 1857 domain_crash_synchronous();
kaf24@9703 1858 }
kaf24@9703 1859 }
kaf24@9703 1860 #endif
kaf24@9703 1861 }
kaf24@9703 1862 }
kaf24@9703 1863 else if (value & X86_CR4_PAE) {
kaf24@9073 1864 set_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
kaf24@9073 1865 } else {
kaf24@9073 1866 if (test_bit(SVM_CPU_STATE_LMA_ENABLED,
kaf24@9073 1867 &v->arch.hvm_svm.cpu_state)) {
kaf24@10082 1868 svm_inject_exception(v, TRAP_gp_fault, 1, 0);
kaf24@9073 1869 }
kaf24@9073 1870 clear_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
kaf24@9073 1871 }
kaf24@9073 1872
kaf24@9073 1873 v->arch.hvm_svm.cpu_shadow_cr4 = value;
kaf24@9073 1874 vmcb->cr4 = value | SVM_CR4_HOST_MASK;
kaf24@8708 1875
kaf24@8708 1876 /*
kaf24@8708 1877 * Writing to CR4 to modify the PSE, PGE, or PAE flag invalidates
kaf24@8708 1878 * all TLB entries except global entries.
kaf24@8708 1879 */
kaf24@8708 1880 if ((old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE))
kaf24@8708 1881 {
kaf24@8708 1882 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
kaf24@8708 1883 shadow_sync_all(v->domain);
kaf24@8708 1884 }
kaf24@8708 1885 break;
kaf24@9703 1886 }
kaf24@8708 1887
kaf24@8708 1888 default:
kaf24@8708 1889 printk("invalid cr: %d\n", cr);
kaf24@8708 1890 __hvm_bug(regs);
kaf24@8708 1891 }
kaf24@8708 1892
kaf24@8708 1893 return 1;
kaf24@8708 1894 }
kaf24@8708 1895
kaf24@8708 1896
kaf24@8708 1897 #define ARR_SIZE(x) (sizeof(x) / sizeof(x[0]))
kaf24@8708 1898
kaf24@8708 1899
kaf24@8708 1900 static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
kaf24@8708 1901 struct cpu_user_regs *regs)
kaf24@8708 1902 {
kaf24@8708 1903 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@9073 1904 int inst_len = 0;
kaf24@9073 1905 int index;
kaf24@8708 1906 unsigned int gpreg;
kaf24@8708 1907 unsigned long value;
kaf24@9073 1908 u8 buffer[MAX_INST_LEN];
kaf24@9073 1909 u8 prefix = 0;
kaf24@8708 1910 int result = 1;
kaf24@8708 1911 enum instruction_index list_a[] = {INSTR_MOV2CR, INSTR_CLTS, INSTR_LMSW};
kaf24@8708 1912 enum instruction_index list_b[] = {INSTR_MOVCR2, INSTR_SMSW};
kaf24@8708 1913 enum instruction_index match;
kaf24@8708 1914
kaf24@8708 1915 ASSERT(vmcb);
kaf24@8708 1916
kaf24@8708 1917 inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
kaf24@9073 1918 /* get index to first actual instruction byte - as we will need to know where the
kaf24@9073 1919 * prefix lives later on
kaf24@9073 1920 */
kaf24@9073 1921 index = skip_prefix_bytes(buffer, sizeof(buffer));
kaf24@8708 1922
kaf24@8708 1923 if (type == TYPE_MOV_TO_CR)
kaf24@8708 1924 {
kaf24@8708 1925 inst_len = __get_instruction_length_from_list(vmcb, list_a,
kaf24@9073 1926 ARR_SIZE(list_a), &buffer[index], &match);
kaf24@8708 1927 }
kaf24@8708 1928 else
kaf24@8708 1929 {
kaf24@8708 1930 inst_len = __get_instruction_length_from_list(vmcb, list_b,
kaf24@9073 1931 ARR_SIZE(list_b), &buffer[index], &match);
kaf24@8708 1932 }
kaf24@8708 1933
kaf24@9073 1934 ASSERT(inst_len > 0);
kaf24@9073 1935
kaf24@9073 1936 inst_len += index;
kaf24@9073 1937
kaf24@9073 1938 /* Check for REX prefix - it's ALWAYS the last byte of any prefix bytes */
kaf24@9073 1939 if (index > 0 && (buffer[index-1] & 0xF0) == 0x40)
kaf24@9073 1940 prefix = buffer[index-1];
kaf24@9073 1941
kaf24@8708 1942 HVM_DBG_LOG(DBG_LEVEL_1, "eip = %lx", (unsigned long) vmcb->rip);
kaf24@8708 1943
kaf24@8708 1944 switch (match)
kaf24@8708 1945 {
kaf24@8708 1946 case INSTR_MOV2CR:
kaf24@9073 1947 gpreg = decode_src_reg(prefix, buffer[index+2]);
kaf24@8708 1948 result = mov_to_cr(gpreg, cr, regs);
kaf24@8708 1949 break;
kaf24@8708 1950
kaf24@8708 1951 case INSTR_MOVCR2:
kaf24@9073 1952 gpreg = decode_src_reg(prefix, buffer[index+2]);
kaf24@8708 1953 mov_from_cr(cr, gpreg, regs);
kaf24@8708 1954 break;
kaf24@8708 1955
kaf24@8708 1956 case INSTR_CLTS:
kaf24@8852 1957 /* TS being cleared means that it's time to restore fpu state. */
kaf24@8708 1958 setup_fpu(current);
kaf24@8852 1959 vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
kaf24@8708 1960 vmcb->cr0 &= ~X86_CR0_TS; /* clear TS */
kaf24@8708 1961 v->arch.hvm_svm.cpu_shadow_cr0 &= ~X86_CR0_TS; /* clear TS */
kaf24@8708 1962 break;
kaf24@8708 1963
kaf24@8708 1964 case INSTR_LMSW:
kaf24@8708 1965 if (svm_dbg_on)
kaf24@8708 1966 svm_dump_inst(svm_rip2pointer(vmcb));
kaf24@8708 1967
kaf24@9073 1968 gpreg = decode_src_reg(prefix, buffer[index+2]);
kaf24@8708 1969 value = get_reg(gpreg, regs, vmcb) & 0xF;
kaf24@8708 1970
kaf24@8708 1971 if (svm_dbg_on)
kaf24@8708 1972 printk("CR0-LMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
kaf24@8708 1973 inst_len);
kaf24@8708 1974
kaf24@8708 1975 value = (v->arch.hvm_svm.cpu_shadow_cr0 & ~0xF) | value;
kaf24@8708 1976
kaf24@8708 1977 if (svm_dbg_on)
kaf24@8708 1978 printk("CR0-LMSW CR0 - New value=%lx\n", value);
kaf24@8708 1979
kaf24@8708 1980 result = svm_set_cr0(value);
kaf24@8708 1981 break;
kaf24@8708 1982
kaf24@8708 1983 case INSTR_SMSW:
kaf24@10081 1984 if (svm_dbg_on)
kaf24@10081 1985 svm_dump_inst(svm_rip2pointer(vmcb));
kaf24@8708 1986 value = v->arch.hvm_svm.cpu_shadow_cr0;
kaf24@9073 1987 gpreg = decode_src_reg(prefix, buffer[index+2]);
kaf24@8708 1988 set_reg(gpreg, value, regs, vmcb);
kaf24@8708 1989
kaf24@8708 1990 if (svm_dbg_on)
kaf24@8708 1991 printk("CR0-SMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
kaf24@8708 1992 inst_len);
kaf24@8708 1993 break;
kaf24@8708 1994
kaf24@8708 1995 default:
kaf24@8708 1996 __hvm_bug(regs);
kaf24@8708 1997 break;
kaf24@8708 1998 }
kaf24@8708 1999
kaf24@8708 2000 ASSERT(inst_len);
kaf24@8708 2001
kaf24@8708 2002 __update_guest_eip(vmcb, inst_len);
kaf24@8708 2003
kaf24@8708 2004 return result;
kaf24@8708 2005 }
kaf24@8708 2006
kfraser@10892 2007 static inline void svm_do_msr_access(
kfraser@10892 2008 struct vcpu *v, struct cpu_user_regs *regs)
kaf24@8708 2009 {
kaf24@8708 2010 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@9073 2011 int inst_len;
kaf24@9416 2012 u64 msr_content=0;
kfraser@10892 2013 u32 eax, edx;
kaf24@8708 2014
kaf24@8708 2015 ASSERT(vmcb);
kaf24@8708 2016
kaf24@8708 2017 HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access: ecx=%lx, eax=%lx, edx=%lx, "
kaf24@8708 2018 "exitinfo = %lx", (unsigned long)regs->ecx,
kaf24@8708 2019 (unsigned long)regs->eax, (unsigned long)regs->edx,
kaf24@8708 2020 (unsigned long)vmcb->exitinfo1);
kaf24@8708 2021
kaf24@8708 2022 /* is it a read? */
kaf24@8708 2023 if (vmcb->exitinfo1 == 0)
kaf24@8708 2024 {
kaf24@8708 2025 inst_len = __get_instruction_length(vmcb, INSTR_RDMSR, NULL);
kaf24@8708 2026
kaf24@8708 2027 regs->edx = 0;
kaf24@9416 2028 switch (regs->ecx) {
kaf24@9416 2029 case MSR_IA32_TIME_STAMP_COUNTER:
kaf24@10182 2030 msr_content = hvm_get_guest_time(v);
kaf24@9416 2031 break;
kaf24@8708 2032 case MSR_IA32_SYSENTER_CS:
kaf24@9416 2033 msr_content = vmcb->sysenter_cs;
kaf24@8708 2034 break;
kaf24@8708 2035 case MSR_IA32_SYSENTER_ESP:
kaf24@9416 2036 msr_content = vmcb->sysenter_esp;
kaf24@8708 2037 break;
kaf24@8708 2038 case MSR_IA32_SYSENTER_EIP:
kaf24@9416 2039 msr_content = vmcb->sysenter_eip;
kaf24@8708 2040 break;
kaf24@9416 2041 case MSR_IA32_APICBASE:
kaf24@9416 2042 msr_content = VLAPIC(v) ? VLAPIC(v)->apic_base_msr : 0;
kaf24@8708 2043 break;
kaf24@8708 2044 default:
kaf24@8708 2045 if (long_mode_do_msr_read(regs))
kaf24@8708 2046 goto done;
kfraser@10892 2047
kfraser@10892 2048 if ( rdmsr_hypervisor_regs(regs->ecx, &eax, &edx) )
kfraser@10892 2049 {
kfraser@10892 2050 regs->eax = eax;
kfraser@10892 2051 regs->edx = edx;
kfraser@10892 2052 goto done;
kfraser@10892 2053 }
kfraser@10892 2054
kaf24@8846 2055 rdmsr_safe(regs->ecx, regs->eax, regs->edx);
kaf24@8708 2056 break;
kaf24@8708 2057 }
kaf24@9416 2058 regs->eax = msr_content & 0xFFFFFFFF;
kaf24@9416 2059 regs->edx = msr_content >> 32;
kaf24@8708 2060 }
kaf24@8708 2061 else
kaf24@8708 2062 {
kaf24@8708 2063 inst_len = __get_instruction_length(vmcb, INSTR_WRMSR, NULL);
kaf24@9416 2064 msr_content = (regs->eax & 0xFFFFFFFF) | ((u64)regs->edx << 32);
kaf24@8708 2065
kaf24@8708 2066 switch (regs->ecx)
kaf24@8708 2067 {
kaf24@9416 2068 case MSR_IA32_TIME_STAMP_COUNTER:
kaf24@9416 2069 svm_set_guest_time(v, msr_content);
kaf24@9416 2070 break;
kaf24@8708 2071 case MSR_IA32_SYSENTER_CS:
kaf24@9416 2072 vmcb->sysenter_cs = msr_content;
kaf24@8708 2073 break;
kaf24@8708 2074 case MSR_IA32_SYSENTER_ESP:
kaf24@9416 2075 vmcb->sysenter_esp = msr_content;
kaf24@8708 2076 break;
kaf24@8708 2077 case MSR_IA32_SYSENTER_EIP:
kaf24@9416 2078 vmcb->sysenter_eip = msr_content;
kaf24@9416 2079 break;
kaf24@9416 2080 case MSR_IA32_APICBASE:
kaf24@9416 2081 vlapic_msr_set(VLAPIC(v), msr_content);
kaf24@8708 2082 break;
kaf24@8708 2083 default:
kfraser@10892 2084 if ( !long_mode_do_msr_write(regs) )
kfraser@10892 2085 wrmsr_hypervisor_regs(regs->ecx, regs->eax, regs->edx);
kaf24@8708 2086 break;
kaf24@8708 2087 }
kaf24@8708 2088 }
kaf24@8708 2089
kaf24@8708 2090 done:
kaf24@8708 2091
kaf24@8708 2092 HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access returns: "
kaf24@8708 2093 "ecx=%lx, eax=%lx, edx=%lx",
kaf24@8708 2094 (unsigned long)regs->ecx, (unsigned long)regs->eax,
kaf24@8708 2095 (unsigned long)regs->edx);
kaf24@8708 2096
kaf24@8708 2097 __update_guest_eip(vmcb, inst_len);
kaf24@8708 2098 }
kaf24@8708 2099
kaf24@8708 2100
kaf24@8708 2101 /*
kaf24@8708 2102 * Need to use this exit to reschedule
kaf24@8708 2103 */
kaf24@8708 2104 static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb)
kaf24@8708 2105 {
kaf24@8708 2106 struct vcpu *v = current;
kaf24@10182 2107 struct periodic_time *pt=&v->domain->arch.hvm_domain.pl_time.periodic_tm;
kaf24@8708 2108 s_time_t next_pit = -1, next_wakeup;
kaf24@8852 2109
kaf24@8852 2110 __update_guest_eip(vmcb, 1);
kaf24@8708 2111
kaf24@9383 2112 /* check for interrupt not handled or new interrupt */
kaf24@9383 2113 if ( vmcb->vintr.fields.irq || cpu_has_pending_irq(v) )
kaf24@9383 2114 return;
kaf24@9383 2115
kaf24@8843 2116 if ( !v->vcpu_id )
kaf24@10182 2117 next_pit = get_scheduled(v, pt->irq, pt);
kaf24@8708 2118 next_wakeup = get_apictime_scheduled(v);
kaf24@8843 2119 if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 )
kaf24@8708 2120 next_wakeup = next_pit;
kaf24@8708 2121 if ( next_wakeup != - 1 )
kaf24@8708 2122 set_timer(&current->arch.hvm_svm.hlt_timer, next_wakeup);
kaf24@8843 2123 hvm_safe_block();
kaf24@8708 2124 }
kaf24@8708 2125
kaf24@8708 2126
kaf24@10081 2127 static void svm_vmexit_do_invd(struct vmcb_struct *vmcb)
kaf24@8708 2128 {
kaf24@10081 2129 int inst_len;
kaf24@10081 2130
kaf24@10081 2131 /* Invalidate the cache - we can't really do that safely - maybe we should
kaf24@10081 2132 * WBINVD, but I think it's just fine to completely ignore it - we should
kaf24@10081 2133 * have cache-snooping that solves it anyways. -- Mats P.
kaf24@10081 2134 */
kaf24@10081 2135
kaf24@10081 2136 /* Tell the user that we did this - just in case someone runs some really weird
kaf24@10081 2137 * operating system and wants to know why it's not working as it should...
kaf24@10081 2138 */
kaf24@10081 2139 printk("INVD instruction intercepted - ignored\n");
kaf24@10081 2140
kaf24@10081 2141 inst_len = __get_instruction_length(vmcb, INSTR_INVD, NULL);
kaf24@10081 2142 __update_guest_eip(vmcb, inst_len);
kaf24@10081 2143 }
kaf24@10081 2144
kaf24@10081 2145
kaf24@8708 2146
kaf24@8708 2147
kaf24@8708 2148 #ifdef XEN_DEBUGGER
kaf24@8708 2149 static void svm_debug_save_cpu_user_regs(struct vmcb_struct *vmcb,
kaf24@8708 2150 struct cpu_user_regs *regs)
kaf24@8708 2151 {
kaf24@8708 2152 regs->eip = vmcb->rip;
kaf24@8708 2153 regs->esp = vmcb->rsp;
kaf24@8708 2154 regs->eflags = vmcb->rflags;
kaf24@8708 2155
kaf24@8708 2156 regs->xcs = vmcb->cs.sel;
kaf24@8708 2157 regs->xds = vmcb->ds.sel;
kaf24@8708 2158 regs->xes = vmcb->es.sel;
kaf24@8708 2159 regs->xfs = vmcb->fs.sel;
kaf24@8708 2160 regs->xgs = vmcb->gs.sel;
kaf24@8708 2161 regs->xss = vmcb->ss.sel;
kaf24@8708 2162 }
kaf24@8708 2163
kaf24@8708 2164
kaf24@8708 2165 static void svm_debug_restore_cpu_user_regs(struct cpu_user_regs *regs)
kaf24@8708 2166 {
kaf24@8708 2167 vmcb->ss.sel = regs->xss;
kaf24@8708 2168 vmcb->rsp = regs->esp;
kaf24@8708 2169 vmcb->rflags = regs->eflags;
kaf24@8708 2170 vmcb->cs.sel = regs->xcs;
kaf24@8708 2171 vmcb->rip = regs->eip;
kaf24@8708 2172
kaf24@8708 2173 vmcb->gs.sel = regs->xgs;
kaf24@8708 2174 vmcb->fs.sel = regs->xfs;
kaf24@8708 2175 vmcb->es.sel = regs->xes;
kaf24@8708 2176 vmcb->ds.sel = regs->xds;
kaf24@8708 2177 }
kaf24@8708 2178 #endif
kaf24@8708 2179
kaf24@8708 2180
kaf24@8708 2181 void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
kaf24@8708 2182 {
kaf24@8708 2183 struct vcpu *v = current;
kfraser@10231 2184 u8 opcode[MAX_INST_LEN], prefix, length = MAX_INST_LEN;
kaf24@8708 2185 unsigned long g_vaddr;
kaf24@9073 2186 int inst_len;
kaf24@8708 2187 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 2188
kaf24@8708 2189 ASSERT(vmcb);
kaf24@8708 2190 /*
kaf24@8708 2191 * Unknown how many bytes the invlpg instruction will take. Use the
kaf24@8708 2192 * maximum instruction length here
kaf24@8708 2193 */
kaf24@8708 2194 if (inst_copy_from_guest(opcode, svm_rip2pointer(vmcb), length) < length)
kaf24@8708 2195 {
kaf24@8708 2196 printk("svm_handle_invlpg (): Error reading memory %d bytes\n", length);
kaf24@8708 2197 __hvm_bug(regs);
kaf24@8708 2198 }
kaf24@8708 2199
kaf24@8708 2200 if (invlpga)
kaf24@8708 2201 {
kaf24@8708 2202 inst_len = __get_instruction_length(vmcb, INSTR_INVLPGA, opcode);
kaf24@9073 2203 ASSERT(inst_len > 0);
kaf24@8708 2204 __update_guest_eip(vmcb, inst_len);
kaf24@8708 2205
kaf24@8708 2206 /*
kaf24@10081 2207 * The address is implicit on this instruction. At the moment, we don't
kaf24@8708 2208 * use ecx (ASID) to identify individual guests pages
kaf24@8708 2209 */
kaf24@8708 2210 g_vaddr = regs->eax;
kaf24@8708 2211 }
kaf24@8708 2212 else
kaf24@8708 2213 {
kaf24@8708 2214 /* What about multiple prefix codes? */
kaf24@8708 2215 prefix = (is_prefix(opcode[0])?opcode[0]:0);
kaf24@8708 2216 inst_len = __get_instruction_length(vmcb, INSTR_INVLPG, opcode);
kaf24@9073 2217 ASSERT(inst_len > 0);
kaf24@8708 2218
kaf24@8708 2219 inst_len--;
kaf24@8708 2220 length -= inst_len;
kaf24@8708 2221
kaf24@8708 2222 /*
kaf24@8708 2223 * Decode memory operand of the instruction including ModRM, SIB, and
kaf24@8708 2224 * displacement to get effecticve address and length in bytes. Assume
kaf24@8708 2225 * the system in either 32- or 64-bit mode.
kaf24@8708 2226 */
kaf24@8708 2227 g_vaddr = get_effective_addr_modrm64(vmcb, regs, prefix,
kaf24@8708 2228 &opcode[inst_len], &length);
kaf24@8708 2229
kaf24@8708 2230 inst_len += length;
kaf24@8708 2231 __update_guest_eip (vmcb, inst_len);
kaf24@8708 2232 }
kaf24@8708 2233
kaf24@8708 2234 /* Overkill, we may not this */
kaf24@8708 2235 set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
kaf24@8708 2236 shadow_invlpg(v, g_vaddr);
kaf24@8708 2237 }
kaf24@8708 2238
kaf24@8708 2239
kaf24@8708 2240 /*
kaf24@8708 2241 * Reset to realmode causes execution to start at 0xF000:0xFFF0 in
kaf24@8708 2242 * 16-bit realmode. Basically, this mimics a processor reset.
kaf24@8708 2243 *
kaf24@8708 2244 * returns 0 on success, non-zero otherwise
kaf24@8708 2245 */
kaf24@8708 2246 static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v,
kaf24@8708 2247 struct cpu_user_regs *regs)
kaf24@8708 2248 {
kaf24@8708 2249 struct vmcb_struct *vmcb;
kaf24@8708 2250
kaf24@8708 2251 ASSERT(v);
kaf24@8708 2252 ASSERT(regs);
kaf24@8708 2253
kaf24@8708 2254 vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 2255
kaf24@8708 2256 ASSERT(vmcb);
kaf24@8708 2257
kaf24@8708 2258 /* clear the vmcb and user regs */
kaf24@8708 2259 memset(regs, 0, sizeof(struct cpu_user_regs));
kaf24@8708 2260
kaf24@8708 2261 /* VMCB Control */
kaf24@8708 2262 vmcb->tsc_offset = 0;
kaf24@8708 2263
kaf24@8708 2264 /* VMCB State */
kaf24@8708 2265 vmcb->cr0 = X86_CR0_ET | X86_CR0_PG;
kaf24@8708 2266 v->arch.hvm_svm.cpu_shadow_cr0 = X86_CR0_ET;
kaf24@8708 2267
kaf24@8708 2268 vmcb->cr2 = 0;
kaf24@9073 2269 vmcb->efer = EFER_SVME;
kaf24@9073 2270
kaf24@9073 2271 vmcb->cr4 = SVM_CR4_HOST_MASK;
kaf24@9073 2272 v->arch.hvm_svm.cpu_shadow_cr4 = 0;
kaf24@9703 2273 clear_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
kaf24@8708 2274
kaf24@8708 2275 /* This will jump to ROMBIOS */
kaf24@8708 2276 vmcb->rip = 0xFFF0;
kaf24@8708 2277
kaf24@8708 2278 /* setup the segment registers and all their hidden states */
kaf24@8708 2279 vmcb->cs.sel = 0xF000;
kaf24@8708 2280 vmcb->cs.attributes.bytes = 0x089b;
kaf24@8708 2281 vmcb->cs.limit = 0xffff;
kaf24@8708 2282 vmcb->cs.base = 0x000F0000;
kaf24@8708 2283
kaf24@8708 2284 vmcb->ss.sel = 0x00;
kaf24@8708 2285 vmcb->ss.attributes.bytes = 0x0893;
kaf24@8708 2286 vmcb->ss.limit = 0xffff;
kaf24@8708 2287 vmcb->ss.base = 0x00;
kaf24@8708 2288
kaf24@8708 2289 vmcb->ds.sel = 0x00;
kaf24@8708 2290 vmcb->ds.attributes.bytes = 0x0893;
kaf24@8708 2291 vmcb->ds.limit = 0xffff;
kaf24@8708 2292 vmcb->ds.base = 0x00;
kaf24@8708 2293
kaf24@8708 2294 vmcb->es.sel = 0x00;
kaf24@8708 2295 vmcb->es.attributes.bytes = 0x0893;
kaf24@8708 2296 vmcb->es.limit = 0xffff;
kaf24@8708 2297 vmcb->es.base = 0x00;
kaf24@8708 2298
kaf24@8708 2299 vmcb->fs.sel = 0x00;
kaf24@8708 2300 vmcb->fs.attributes.bytes = 0x0893;
kaf24@8708 2301 vmcb->fs.limit = 0xffff;
kaf24@8708 2302 vmcb->fs.base = 0x00;
kaf24@8708 2303
kaf24@8708 2304 vmcb->gs.sel = 0x00;
kaf24@8708 2305 vmcb->gs.attributes.bytes = 0x0893;
kaf24@8708 2306 vmcb->gs.limit = 0xffff;
kaf24@8708 2307 vmcb->gs.base = 0x00;
kaf24@8708 2308
kaf24@8708 2309 vmcb->ldtr.sel = 0x00;
kaf24@8708 2310 vmcb->ldtr.attributes.bytes = 0x0000;
kaf24@8708 2311 vmcb->ldtr.limit = 0x0;
kaf24@8708 2312 vmcb->ldtr.base = 0x00;
kaf24@8708 2313
kaf24@8708 2314 vmcb->gdtr.sel = 0x00;
kaf24@8708 2315 vmcb->gdtr.attributes.bytes = 0x0000;
kaf24@8708 2316 vmcb->gdtr.limit = 0x0;
kaf24@8708 2317 vmcb->gdtr.base = 0x00;
kaf24@8708 2318
kaf24@8708 2319 vmcb->tr.sel = 0;
kaf24@8708 2320 vmcb->tr.attributes.bytes = 0;
kaf24@8708 2321 vmcb->tr.limit = 0x0;
kaf24@8708 2322 vmcb->tr.base = 0;
kaf24@8708 2323
kaf24@8708 2324 vmcb->idtr.sel = 0x00;
kaf24@8708 2325 vmcb->idtr.attributes.bytes = 0x0000;
kaf24@8708 2326 vmcb->idtr.limit = 0x3ff;
kaf24@8708 2327 vmcb->idtr.base = 0x00;
kaf24@8708 2328
kaf24@8708 2329 vmcb->rax = 0;
kaf24@9704 2330 vmcb->rsp = 0;
kaf24@8708 2331
kaf24@8708 2332 return 0;
kaf24@8708 2333 }
kaf24@8708 2334
kaf24@8708 2335
kaf24@8708 2336 /*
kaf24@8708 2337 * svm_do_vmmcall - SVM VMMCALL handler
kaf24@8708 2338 *
kaf24@8708 2339 * returns 0 on success, non-zero otherwise
kaf24@8708 2340 */
kaf24@8708 2341 static int svm_do_vmmcall(struct vcpu *v, struct cpu_user_regs *regs)
kaf24@8708 2342 {
kaf24@8708 2343 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@9073 2344 int inst_len;
kaf24@8708 2345
kaf24@8708 2346 ASSERT(vmcb);
kaf24@8708 2347 ASSERT(regs);
kaf24@8708 2348
kaf24@8708 2349 inst_len = __get_instruction_length(vmcb, INSTR_VMCALL, NULL);
kaf24@9073 2350 ASSERT(inst_len > 0);
kaf24@8708 2351
kaf24@8708 2352 /* VMMCALL sanity check */
kaf24@8708 2353 if (vmcb->cpl > get_vmmcall_cpl(regs->edi))
kaf24@8708 2354 {
kaf24@8708 2355 printf("VMMCALL CPL check failed\n");
kaf24@8708 2356 return -1;
kaf24@8708 2357 }
kaf24@8708 2358
kaf24@8708 2359 /* handle the request */
kaf24@8708 2360 switch (regs->edi)
kaf24@8708 2361 {
kaf24@8708 2362 case VMMCALL_RESET_TO_REALMODE:
kaf24@8708 2363 if (svm_do_vmmcall_reset_to_realmode(v, regs))
kaf24@8708 2364 {
kaf24@8708 2365 printf("svm_do_vmmcall_reset_to_realmode() failed\n");
kaf24@8708 2366 return -1;
kaf24@8708 2367 }
kaf24@8708 2368
kaf24@8708 2369 /* since we just reset the VMCB, return without adjusting the eip */
kaf24@8708 2370 return 0;
kaf24@8708 2371 case VMMCALL_DEBUG:
kaf24@8708 2372 printf("DEBUG features not implemented yet\n");
kaf24@8708 2373 break;
kaf24@8708 2374 default:
kaf24@8708 2375 break;
kaf24@8708 2376 }
kaf24@8708 2377
kaf24@8708 2378 hvm_print_line(v, regs->eax); /* provides the current domain */
kaf24@8708 2379
kaf24@8708 2380 __update_guest_eip(vmcb, inst_len);
kaf24@8708 2381 return 0;
kaf24@8708 2382 }
kaf24@8708 2383
kaf24@8708 2384
kaf24@8708 2385 void svm_dump_inst(unsigned long eip)
kaf24@8708 2386 {
kaf24@8708 2387 u8 opcode[256];
kaf24@8708 2388 unsigned long ptr;
kaf24@8708 2389 int len;
kaf24@8708 2390 int i;
kaf24@8708 2391
kaf24@8708 2392 ptr = eip & ~0xff;
kaf24@8708 2393 len = 0;
kaf24@8708 2394
kaf24@8708 2395 if (hvm_copy(opcode, ptr, sizeof(opcode), HVM_COPY_IN))
kaf24@8708 2396 len = sizeof(opcode);
kaf24@8708 2397
kaf24@8708 2398 printf("Code bytes around(len=%d) %lx:", len, eip);
kaf24@8708 2399 for (i = 0; i < len; i++)
kaf24@8708 2400 {
kaf24@8708 2401 if ((i & 0x0f) == 0)
kaf24@8708 2402 printf("\n%08lx:", ptr+i);
kaf24@8708 2403
kaf24@8708 2404 printf("%02x ", opcode[i]);
kaf24@8708 2405 }
kaf24@8708 2406
kaf24@8708 2407 printf("\n");
kaf24@8708 2408 }
kaf24@8708 2409
kaf24@8708 2410
kaf24@8708 2411 void svm_dump_regs(const char *from, struct cpu_user_regs *regs)
kaf24@8708 2412 {
kaf24@8708 2413 struct vcpu *v = current;
kaf24@8708 2414 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 2415 unsigned long pt = pagetable_get_paddr(v->arch.shadow_table);
kaf24@8708 2416
kaf24@8708 2417 printf("%s: guest registers from %s:\n", __func__, from);
kaf24@8708 2418 #if defined (__x86_64__)
kaf24@8708 2419 printk("rax: %016lx rbx: %016lx rcx: %016lx\n",
kaf24@8708 2420 regs->rax, regs->rbx, regs->rcx);
kaf24@8708 2421 printk("rdx: %016lx rsi: %016lx rdi: %016lx\n",
kaf24@8708 2422 regs->rdx, regs->rsi, regs->rdi);
kaf24@8708 2423 printk("rbp: %016lx rsp: %016lx r8: %016lx\n",
kaf24@8708 2424 regs->rbp, regs->rsp, regs->r8);
kaf24@8708 2425 printk("r9: %016lx r10: %016lx r11: %016lx\n",
kaf24@8708 2426 regs->r9, regs->r10, regs->r11);
kaf24@8708 2427 printk("r12: %016lx r13: %016lx r14: %016lx\n",
kaf24@8708 2428 regs->r12, regs->r13, regs->r14);
kaf24@8708 2429 printk("r15: %016lx cr0: %016lx cr3: %016lx\n",
kaf24@8708 2430 regs->r15, v->arch.hvm_svm.cpu_shadow_cr0, vmcb->cr3);
kaf24@8708 2431 #else
kaf24@8708 2432 printf("eax: %08x, ebx: %08x, ecx: %08x, edx: %08x\n",
kaf24@8708 2433 regs->eax, regs->ebx, regs->ecx, regs->edx);
kaf24@8708 2434 printf("edi: %08x, esi: %08x, ebp: %08x, esp: %08x\n",
kaf24@8708 2435 regs->edi, regs->esi, regs->ebp, regs->esp);
kaf24@8708 2436 printf("%s: guest cr0: %lx\n", __func__,
kaf24@8708 2437 v->arch.hvm_svm.cpu_shadow_cr0);
kaf24@8708 2438 printf("guest CR3 = %llx\n", vmcb->cr3);
kaf24@8708 2439 #endif
kaf24@8708 2440 printf("%s: pt = %lx\n", __func__, pt);
kaf24@8708 2441 }
kaf24@8708 2442
kaf24@8708 2443
kaf24@8708 2444 void svm_dump_host_regs(const char *from)
kaf24@8708 2445 {
kaf24@8708 2446 struct vcpu *v = current;
kaf24@8708 2447 unsigned long pt = pt = pagetable_get_paddr(v->arch.monitor_table);
kaf24@8708 2448 unsigned long cr3, cr0;
kaf24@8708 2449 printf("Host registers at %s\n", from);
kaf24@8708 2450
kaf24@8708 2451 __asm__ __volatile__ ("\tmov %%cr0,%0\n"
kaf24@8708 2452 "\tmov %%cr3,%1\n"
kaf24@8708 2453 : "=r" (cr0), "=r"(cr3));
kaf24@8708 2454 printf("%s: pt = %lx, cr3 = %lx, cr0 = %lx\n", __func__, pt, cr3, cr0);
kaf24@8708 2455 }
kaf24@8708 2456
kaf24@8708 2457 #ifdef SVM_EXTRA_DEBUG
kaf24@8708 2458 static char *exit_reasons[] = {
kaf24@8708 2459 [VMEXIT_CR0_READ] = "CR0_READ",
kaf24@8708 2460 [VMEXIT_CR1_READ] = "CR1_READ",
kaf24@8708 2461 [VMEXIT_CR2_READ] = "CR2_READ",
kaf24@8708 2462 [VMEXIT_CR3_READ] = "CR3_READ",
kaf24@8708 2463 [VMEXIT_CR4_READ] = "CR4_READ",
kaf24@8708 2464 [VMEXIT_CR5_READ] = "CR5_READ",
kaf24@8708 2465 [VMEXIT_CR6_READ] = "CR6_READ",
kaf24@8708 2466 [VMEXIT_CR7_READ] = "CR7_READ",
kaf24@8708 2467 [VMEXIT_CR8_READ] = "CR8_READ",
kaf24@8708 2468 [VMEXIT_CR9_READ] = "CR9_READ",
kaf24@8708 2469 [VMEXIT_CR10_READ] = "CR10_READ",
kaf24@8708 2470 [VMEXIT_CR11_READ] = "CR11_READ",
kaf24@8708 2471 [VMEXIT_CR12_READ] = "CR12_READ",
kaf24@8708 2472 [VMEXIT_CR13_READ] = "CR13_READ",
kaf24@8708 2473 [VMEXIT_CR14_READ] = "CR14_READ",
kaf24@8708 2474 [VMEXIT_CR15_READ] = "CR15_READ",
kaf24@8708 2475 [VMEXIT_CR0_WRITE] = "CR0_WRITE",
kaf24@8708 2476 [VMEXIT_CR1_WRITE] = "CR1_WRITE",
kaf24@8708 2477 [VMEXIT_CR2_WRITE] = "CR2_WRITE",
kaf24@8708 2478 [VMEXIT_CR3_WRITE] = "CR3_WRITE",
kaf24@8708 2479 [VMEXIT_CR4_WRITE] = "CR4_WRITE",
kaf24@8708 2480 [VMEXIT_CR5_WRITE] = "CR5_WRITE",
kaf24@8708 2481 [VMEXIT_CR6_WRITE] = "CR6_WRITE",
kaf24@8708 2482 [VMEXIT_CR7_WRITE] = "CR7_WRITE",
kaf24@8708 2483 [VMEXIT_CR8_WRITE] = "CR8_WRITE",
kaf24@8708 2484 [VMEXIT_CR9_WRITE] = "CR9_WRITE",
kaf24@8708 2485 [VMEXIT_CR10_WRITE] = "CR10_WRITE",
kaf24@8708 2486 [VMEXIT_CR11_WRITE] = "CR11_WRITE",
kaf24@8708 2487 [VMEXIT_CR12_WRITE] = "CR12_WRITE",
kaf24@8708 2488 [VMEXIT_CR13_WRITE] = "CR13_WRITE",
kaf24@8708 2489 [VMEXIT_CR14_WRITE] = "CR14_WRITE",
kaf24@8708 2490 [VMEXIT_CR15_WRITE] = "CR15_WRITE",
kaf24@8708 2491 [VMEXIT_DR0_READ] = "DR0_READ",
kaf24@8708 2492 [VMEXIT_DR1_READ] = "DR1_READ",
kaf24@8708 2493 [VMEXIT_DR2_READ] = "DR2_READ",
kaf24@8708 2494 [VMEXIT_DR3_READ] = "DR3_READ",
kaf24@8708 2495 [VMEXIT_DR4_READ] = "DR4_READ",
kaf24@8708 2496 [VMEXIT_DR5_READ] = "DR5_READ",
kaf24@8708 2497 [VMEXIT_DR6_READ] = "DR6_READ",
kaf24@8708 2498 [VMEXIT_DR7_READ] = "DR7_READ",
kaf24@8708 2499 [VMEXIT_DR8_READ] = "DR8_READ",
kaf24@8708 2500 [VMEXIT_DR9_READ] = "DR9_READ",
kaf24@8708 2501 [VMEXIT_DR10_READ] = "DR10_READ",
kaf24@8708 2502 [VMEXIT_DR11_READ] = "DR11_READ",
kaf24@8708 2503 [VMEXIT_DR12_READ] = "DR12_READ",
kaf24@8708 2504 [VMEXIT_DR13_READ] = "DR13_READ",
kaf24@8708 2505 [VMEXIT_DR14_READ] = "DR14_READ",
kaf24@8708 2506 [VMEXIT_DR15_READ] = "DR15_READ",
kaf24@8708 2507 [VMEXIT_DR0_WRITE] = "DR0_WRITE",
kaf24@8708 2508 [VMEXIT_DR1_WRITE] = "DR1_WRITE",
kaf24@8708 2509 [VMEXIT_DR2_WRITE] = "DR2_WRITE",
kaf24@8708 2510 [VMEXIT_DR3_WRITE] = "DR3_WRITE",
kaf24@8708 2511 [VMEXIT_DR4_WRITE] = "DR4_WRITE",
kaf24@8708 2512 [VMEXIT_DR5_WRITE] = "DR5_WRITE",
kaf24@8708 2513 [VMEXIT_DR6_WRITE] = "DR6_WRITE",
kaf24@8708 2514 [VMEXIT_DR7_WRITE] = "DR7_WRITE",
kaf24@8708 2515 [VMEXIT_DR8_WRITE] = "DR8_WRITE",
kaf24@8708 2516 [VMEXIT_DR9_WRITE] = "DR9_WRITE",
kaf24@8708 2517 [VMEXIT_DR10_WRITE] = "DR10_WRITE",
kaf24@8708 2518 [VMEXIT_DR11_WRITE] = "DR11_WRITE",
kaf24@8708 2519 [VMEXIT_DR12_WRITE] = "DR12_WRITE",
kaf24@8708 2520 [VMEXIT_DR13_WRITE] = "DR13_WRITE",
kaf24@8708 2521 [VMEXIT_DR14_WRITE] = "DR14_WRITE",
kaf24@8708 2522 [VMEXIT_DR15_WRITE] = "DR15_WRITE",
kaf24@8708 2523 [VMEXIT_EXCEPTION_DE] = "EXCEPTION_DE",
kaf24@8708 2524 [VMEXIT_EXCEPTION_DB] = "EXCEPTION_DB",
kaf24@8708 2525 [VMEXIT_EXCEPTION_NMI] = "EXCEPTION_NMI",
kaf24@8708 2526 [VMEXIT_EXCEPTION_BP] = "EXCEPTION_BP",
kaf24@8708 2527 [VMEXIT_EXCEPTION_OF] = "EXCEPTION_OF",
kaf24@8708 2528 [VMEXIT_EXCEPTION_BR] = "EXCEPTION_BR",
kaf24@8708 2529 [VMEXIT_EXCEPTION_UD] = "EXCEPTION_UD",
kaf24@8708 2530 [VMEXIT_EXCEPTION_NM] = "EXCEPTION_NM",
kaf24@8708 2531 [VMEXIT_EXCEPTION_DF] = "EXCEPTION_DF",
kaf24@8708 2532 [VMEXIT_EXCEPTION_09] = "EXCEPTION_09",
kaf24@8708 2533 [VMEXIT_EXCEPTION_TS] = "EXCEPTION_TS",
kaf24@8708 2534 [VMEXIT_EXCEPTION_NP] = "EXCEPTION_NP",
kaf24@8708 2535 [VMEXIT_EXCEPTION_SS] = "EXCEPTION_SS",
kaf24@8708 2536 [VMEXIT_EXCEPTION_GP] = "EXCEPTION_GP",
kaf24@8708 2537 [VMEXIT_EXCEPTION_PF] = "EXCEPTION_PF",
kaf24@8708 2538 [VMEXIT_EXCEPTION_15] = "EXCEPTION_15",
kaf24@8708 2539 [VMEXIT_EXCEPTION_MF] = "EXCEPTION_MF",
kaf24@8708 2540 [VMEXIT_EXCEPTION_AC] = "EXCEPTION_AC",
kaf24@8708 2541 [VMEXIT_EXCEPTION_MC] = "EXCEPTION_MC",
kaf24@8708 2542 [VMEXIT_EXCEPTION_XF] = "EXCEPTION_XF",
kaf24@8708 2543 [VMEXIT_INTR] = "INTR",
kaf24@8708 2544 [VMEXIT_NMI] = "NMI",
kaf24@8708 2545 [VMEXIT_SMI] = "SMI",
kaf24@8708 2546 [VMEXIT_INIT] = "INIT",
kaf24@8708 2547 [VMEXIT_VINTR] = "VINTR",
kaf24@8708 2548 [VMEXIT_CR0_SEL_WRITE] = "CR0_SEL_WRITE",
kaf24@8708 2549 [VMEXIT_IDTR_READ] = "IDTR_READ",
kaf24@8708 2550 [VMEXIT_GDTR_READ] = "GDTR_READ",
kaf24@8708 2551 [VMEXIT_LDTR_READ] = "LDTR_READ",
kaf24@8708 2552 [VMEXIT_TR_READ] = "TR_READ",
kaf24@8708 2553 [VMEXIT_IDTR_WRITE] = "IDTR_WRITE",
kaf24@8708 2554 [VMEXIT_GDTR_WRITE] = "GDTR_WRITE",
kaf24@8708 2555 [VMEXIT_LDTR_WRITE] = "LDTR_WRITE",
kaf24@8708 2556 [VMEXIT_TR_WRITE] = "TR_WRITE",
kaf24@8708 2557 [VMEXIT_RDTSC] = "RDTSC",
kaf24@8708 2558 [VMEXIT_RDPMC] = "RDPMC",
kaf24@8708 2559 [VMEXIT_PUSHF] = "PUSHF",
kaf24@8708 2560 [VMEXIT_POPF] = "POPF",
kaf24@8708 2561 [VMEXIT_CPUID] = "CPUID",
kaf24@8708 2562 [VMEXIT_RSM] = "RSM",
kaf24@8708 2563 [VMEXIT_IRET] = "IRET",
kaf24@8708 2564 [VMEXIT_SWINT] = "SWINT",
kaf24@8708 2565 [VMEXIT_INVD] = "INVD",
kaf24@8708 2566 [VMEXIT_PAUSE] = "PAUSE",
kaf24@8708 2567 [VMEXIT_HLT] = "HLT",
kaf24@8708 2568 [VMEXIT_INVLPG] = "INVLPG",
kaf24@8708 2569 [VMEXIT_INVLPGA] = "INVLPGA",
kaf24@8708 2570 [VMEXIT_IOIO] = "IOIO",
kaf24@8708 2571 [VMEXIT_MSR] = "MSR",
kaf24@8708 2572 [VMEXIT_TASK_SWITCH] = "TASK_SWITCH",
kaf24@8708 2573 [VMEXIT_FERR_FREEZE] = "FERR_FREEZE",
kaf24@8708 2574 [VMEXIT_SHUTDOWN] = "SHUTDOWN",
kaf24@8708 2575 [VMEXIT_VMRUN] = "VMRUN",
kaf24@8708 2576 [VMEXIT_VMMCALL] = "VMMCALL",
kaf24@8708 2577 [VMEXIT_VMLOAD] = "VMLOAD",
kaf24@8708 2578 [VMEXIT_VMSAVE] = "VMSAVE",
kaf24@8708 2579 [VMEXIT_STGI] = "STGI",
kaf24@8708 2580 [VMEXIT_CLGI] = "CLGI",
kaf24@8708 2581 [VMEXIT_SKINIT] = "SKINIT",
kaf24@8708 2582 [VMEXIT_RDTSCP] = "RDTSCP",
kaf24@8708 2583 [VMEXIT_ICEBP] = "ICEBP",
kaf24@8708 2584 [VMEXIT_NPF] = "NPF"
kaf24@8708 2585 };
kaf24@8708 2586 #endif /* SVM_EXTRA_DEBUG */
kaf24@8708 2587
kaf24@8708 2588 #ifdef SVM_WALK_GUEST_PAGES
kaf24@8708 2589 void walk_shadow_and_guest_pt(unsigned long gva)
kaf24@8708 2590 {
kaf24@8708 2591 l2_pgentry_t gpde;
kaf24@8708 2592 l2_pgentry_t spde;
kaf24@8708 2593 l1_pgentry_t gpte;
kaf24@8708 2594 l1_pgentry_t spte;
kaf24@8708 2595 struct vcpu *v = current;
kaf24@8708 2596 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 2597 unsigned long gpa;
kaf24@8708 2598
kaf24@8708 2599 gpa = gva_to_gpa( gva );
kaf24@8708 2600 printk( "gva = %lx, gpa=%lx, gCR3=%x\n", gva, gpa, (u32)vmcb->cr3 );
kaf24@8753 2601 if( !svm_paging_enabled(v) || mmio_space(gpa) )
kaf24@8708 2602 return;
kaf24@8708 2603
kaf24@8708 2604 /* let's dump the guest and shadow page info */
kaf24@8708 2605
kaf24@8708 2606 __guest_get_l2e(v, gva, &gpde);
kaf24@8708 2607 printk( "G-PDE = %x, flags=%x\n", gpde.l2, l2e_get_flags(gpde) );
kaf24@8708 2608 __shadow_get_l2e( v, gva, &spde );
kaf24@8708 2609 printk( "S-PDE = %x, flags=%x\n", spde.l2, l2e_get_flags(spde) );
kaf24@8708 2610
kaf24@8708 2611 if ( unlikely(!(l2e_get_flags(gpde) & _PAGE_PRESENT)) )
kaf24@8708 2612 return;
kaf24@8708 2613
kaf24@8708 2614 spte = l1e_empty();
kaf24@8708 2615
kaf24@10549 2616 /* This is actually overkill - we only need to make sure the hl2 is in-sync. */
kaf24@8708 2617 shadow_sync_va(v, gva);
kaf24@8708 2618
kaf24@8708 2619 gpte.l1 = 0;
kaf24@8708 2620 __copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ], sizeof(gpte) );
kaf24@8708 2621 printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) );
kaf24@9703 2622 __copy_from_user( &spte, &phys_to_machine_mapping[ l1e_get_pfn( gpte ) ],
kaf24@9703 2623 sizeof(spte) );
kaf24@8708 2624 printk( "S-PTE = %x, flags=%x\n", spte.l1, l1e_get_flags(spte));
kaf24@8708 2625 }
kaf24@8708 2626 #endif /* SVM_WALK_GUEST_PAGES */
kaf24@8708 2627
kaf24@8708 2628 asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
kaf24@8708 2629 {
kaf24@8708 2630 unsigned int exit_reason;
kaf24@8708 2631 unsigned long eip;
kaf24@8708 2632 struct vcpu *v = current;
kaf24@8708 2633 int error;
kaf24@8708 2634 int do_debug = 0;
kaf24@8708 2635 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@8708 2636
kaf24@8708 2637 ASSERT(vmcb);
kaf24@8708 2638
kaf24@8708 2639 exit_reason = vmcb->exitcode;
kaf24@8708 2640 save_svm_cpu_user_regs(v, &regs);
kaf24@8708 2641
kaf24@8801 2642 vmcb->tlb_control = 1;
kaf24@8708 2643
kaf24@8708 2644 #ifdef SVM_EXTRA_DEBUG
kaf24@8708 2645 {
kaf24@8708 2646 #if defined(__i386__)
kaf24@8708 2647 #define rip eip
kaf24@8708 2648 #endif
kaf24@8708 2649
kaf24@8708 2650 static unsigned long intercepts_counter = 0;
kaf24@8708 2651
kaf24@8708 2652 if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF)
kaf24@8708 2653 {
kaf24@8708 2654 if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
kaf24@8708 2655 {
kaf24@9703 2656 printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx, gpa=%llx\n",
kaf24@9703 2657 intercepts_counter,
kaf24@9703 2658 exit_reasons[exit_reason], exit_reason, regs.cs,
kaf24@9703 2659 (unsigned long long) regs.rip,
kaf24@9703 2660 (unsigned long long) vmcb->exitinfo1,
kaf24@9703 2661 (unsigned long long) vmcb->exitinfo2,
kaf24@9703 2662 (unsigned long long) vmcb->exitintinfo.bytes,
kaf24@9703 2663 (unsigned long long) gva_to_gpa( vmcb->exitinfo2 ) );
kaf24@9703 2664 }
kaf24@9703 2665 else
kaf24@9703 2666 {
kaf24@8708 2667 printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
kaf24@8708 2668 intercepts_counter,
kaf24@8708 2669 exit_reasons[exit_reason], exit_reason, regs.cs,
kaf24@8708 2670 (unsigned long long) regs.rip,
kaf24@8708 2671 (unsigned long long) vmcb->exitinfo1,
kaf24@8708 2672 (unsigned long long) vmcb->exitinfo2,
kaf24@9703 2673 (unsigned long long) vmcb->exitintinfo.bytes );
kaf24@8708 2674 }
kaf24@8708 2675 }
kaf24@9703 2676 else if ( svm_dbg_on
kaf24@9703 2677 && exit_reason != VMEXIT_IOIO
kaf24@9703 2678 && exit_reason != VMEXIT_INTR)
kaf24@8708 2679 {
kaf24@8708 2680
kaf24@8708 2681 if (exit_reasons[exit_reason])
kaf24@8708 2682 {
kaf24@8708 2683 printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
kaf24@8708 2684 intercepts_counter,
kaf24@8708 2685 exit_reasons[exit_reason], exit_reason, regs.cs,
kaf24@8708 2686 (unsigned long long) regs.rip,
kaf24@8708 2687 (unsigned long long) vmcb->exitinfo1,
kaf24@8708 2688 (unsigned long long) vmcb->exitinfo2,
kaf24@8708 2689 (unsigned long long) vmcb->exitintinfo.bytes);
kaf24@8708 2690 }
kaf24@8708 2691 else
kaf24@8708 2692 {
kaf24@8708 2693 printk("I%08ld,ExC=%d(0x%x),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
kaf24@8708 2694 intercepts_counter, exit_reason, exit_reason, regs.cs,
kaf24@8708 2695 (unsigned long long) regs.rip,
kaf24@8708 2696 (unsigned long long) vmcb->exitinfo1,
kaf24@8708 2697 (unsigned long long) vmcb->exitinfo2,
kaf24@8708 2698 (unsigned long long) vmcb->exitintinfo.bytes);
kaf24@8708 2699 }
kaf24@8708 2700 }
kaf24@8708 2701
kaf24@8708 2702 #ifdef SVM_WALK_GUEST_PAGES
kaf24@9703 2703 if( exit_reason == VMEXIT_EXCEPTION_PF
kaf24@9703 2704 && ( ( vmcb->exitinfo2 == vmcb->rip )
kaf24@9703 2705 || vmcb->exitintinfo.bytes) )
kaf24@8708 2706 {
kaf24@8708 2707 if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
kaf24@8708 2708 walk_shadow_and_guest_pt( vmcb->exitinfo2 );
kaf24@8708 2709 }
kaf24@8708 2710 #endif
kaf24@8708 2711
kaf24@8708 2712 intercepts_counter++;
kaf24@8708 2713
kaf24@8708 2714 #if 0
kaf24@8708 2715 if (svm_dbg_on)
kaf24@8708 2716 do_debug = svm_do_debugout(exit_reason);
kaf24@8708 2717 #endif
kaf24@8708 2718
kaf24@8708 2719 if (do_debug)
kaf24@8708 2720 {
kaf24@8708 2721 printk("%s:+ guest_table = 0x%08x, monitor_table = 0x%08x, "
kaf24@8708 2722 "shadow_table = 0x%08x\n",
kaf24@8708 2723 __func__,
kaf24@8708 2724 (int) v->arch.guest_table.pfn,
kaf24@8708 2725 (int) v->arch.monitor_table.pfn,
kaf24@8708 2726 (int) v->arch.shadow_table.pfn);
kaf24@8708 2727
kaf24@8708 2728 svm_dump_vmcb(__func__, vmcb);
kaf24@8708 2729 svm_dump_regs(__func__, &regs);
kaf24@8708 2730 svm_dump_inst(svm_rip2pointer(vmcb));
kaf24@8708 2731 }
kaf24@8708 2732
kaf24@8708 2733 #if defined(__i386__)
kaf24@8708 2734 #undef rip
kaf24@8708 2735 #endif
kaf24@8708 2736
kaf24@8708 2737 }
kaf24@8708 2738 #endif /* SVM_EXTRA_DEBUG */
kaf24@8708 2739
kaf24@8708 2740 if (exit_reason == -1)
kaf24@8708 2741 {
kaf24@10615 2742 svm_dump_vmcb(__func__, vmcb);
kaf24@8708 2743 printk("%s: exit_reason == -1 - Did someone clobber the VMCB\n",
kaf24@8708 2744 __func__);
kaf24@8708 2745 domain_crash_synchronous();
kaf24@8708 2746 }
kaf24@8708 2747
kaf24@10766 2748 perfc_incra(svmexits, exit_reason);
kaf24@8708 2749 eip = vmcb->rip;
kaf24@8708 2750
kaf24@8708 2751 #ifdef SVM_EXTRA_DEBUG
kaf24@8708 2752 if (do_debug)
kaf24@8708 2753 {
kaf24@8708 2754 printk("eip = %lx, exit_reason = %d (0x%x)\n",
kaf24@8708 2755 eip, exit_reason, exit_reason);
kaf24@8708 2756 }
kaf24@8708 2757 #endif /* SVM_EXTRA_DEBUG */
kaf24@8708 2758
kaf24@8708 2759 TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason);
kaf24@8708 2760
kaf24@8708 2761 switch (exit_reason)
kaf24@8708 2762 {
kaf24@8708 2763 case VMEXIT_EXCEPTION_DB:
kaf24@8708 2764 {
kaf24@8708 2765 #ifdef XEN_DEBUGGER
kaf24@8708 2766 svm_debug_save_cpu_user_regs(&regs);
kaf24@8708 2767 pdb_handle_exception(1, &regs, 1);
kaf24@8708 2768 svm_debug_restore_cpu_user_regs(&regs);
kaf24@8708 2769 #else
kaf24@8708 2770 svm_store_cpu_user_regs(&regs, v);
kaf24@8708 2771 domain_pause_for_debugger();
kaf24@8708 2772 #endif
kaf24@8708 2773 }
kaf24@8708 2774 break;
kaf24@8708 2775
kaf24@8708 2776 case VMEXIT_NMI:
kaf24@8708 2777 do_nmi(&regs, 0);
kaf24@8708 2778 break;
kaf24@8708 2779
kaf24@9384 2780 case VMEXIT_SMI:
kaf24@9384 2781 /*
kaf24@9384 2782 * For asynchronous SMI's, we just need to allow global interrupts
kaf24@9384 2783 * so that the SMI is taken properly in the context of the host. The
kaf24@9384 2784 * standard code does a STGI after the VMEXIT which should accomplish
kaf24@9384 2785 * this task. Continue as normal and restart the guest.
kaf24@9384 2786 */
kaf24@9384 2787 break;
kaf24@9384 2788
kaf24@9702 2789 case VMEXIT_INIT:
kaf24@9702 2790 /*
kaf24@9702 2791 * Nothing to do, in fact we should never get to this point.
kaf24@9702 2792 */
kaf24@9702 2793 break;
kaf24@9702 2794
kaf24@9705 2795 case VMEXIT_EXCEPTION_BP:
kaf24@8708 2796 #ifdef XEN_DEBUGGER
kaf24@8708 2797 svm_debug_save_cpu_user_regs(&regs);
kaf24@8708 2798 pdb_handle_exception(3, &regs, 1);
kaf24@8708 2799 svm_debug_restore_cpu_user_regs(&regs);
kaf24@9705 2800 #else
kaf24@9705 2801 if ( test_bit(_DOMF_debugging, &v->domain->domain_flags) )
kaf24@9705 2802 domain_pause_for_debugger();
kaf24@9705 2803 else
kaf24@10082 2804 svm_inject_exception(v, TRAP_int3, 0, 0);
kaf24@9705 2805 #endif
kaf24@8708 2806 break;
kaf24@8708 2807
kaf24@8708 2808 case VMEXIT_EXCEPTION_NM:
kaf24@8708 2809 svm_do_no_device_fault(vmcb);
kaf24@8708 2810 break;
kaf24@8708 2811
kaf24@8708 2812 case VMEXIT_EXCEPTION_GP:
kaf24@8708 2813 /* This should probably not be trapped in the future */
kaf24@8708 2814 regs.error_code = vmcb->exitinfo1;
kaf24@8708 2815 svm_do_general_protection_fault(v, &regs);
kaf24@8708 2816 break;
kaf24@8708 2817
kaf24@8708 2818 case VMEXIT_EXCEPTION_PF:
kaf24@8708 2819 {
kaf24@8708 2820 unsigned long va;
kaf24@8708 2821 va = vmcb->exitinfo2;
kaf24@8708 2822 regs.error_code = vmcb->exitinfo1;
kaf24@8708 2823 HVM_DBG_LOG(DBG_LEVEL_VMMU,
kaf24@8708 2824 "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
kaf24@8708 2825 (unsigned long)regs.eax, (unsigned long)regs.ebx,
kaf24@8708 2826 (unsigned long)regs.ecx, (unsigned long)regs.edx,
kaf24@8708 2827 (unsigned long)regs.esi, (unsigned long)regs.edi);
kaf24@8708 2828
kaf24@8708 2829 if (!(error = svm_do_page_fault(va, &regs)))
kaf24@8708 2830 {
kaf24@8708 2831 /* Inject #PG using Interruption-Information Fields */
kaf24@10082 2832 svm_inject_exception(v, TRAP_page_fault, 1, regs.error_code);
kaf24@8893 2833
kaf24@8708 2834 v->arch.hvm_svm.cpu_cr2 = va;
kaf24@8708 2835 vmcb->cr2 = va;
kaf24@8708 2836 TRACE_3D(TRC_VMX_INT, v->domain->domain_id,
kaf24@8708 2837 VMEXIT_EXCEPTION_PF, va);
kaf24@8708 2838 }
kaf24@8708 2839 break;
kaf24@8708 2840 }
kaf24@8708 2841
kaf24@8708 2842 case VMEXIT_EXCEPTION_DF:
kaf24@10551 2843 /* Debug info to hopefully help debug WHY the guest double-faulted. */
kaf24@10551 2844 svm_dump_vmcb(__func__, vmcb);
kaf24@10551 2845 svm_dump_regs(__func__, &regs);
kaf24@10551 2846 svm_dump_inst(svm_rip2pointer(vmcb));
kaf24@10551 2847 svm_inject_exception(v, TRAP_double_fault, 1, 0);
kaf24@8708 2848 break;
kaf24@8708 2849
kaf24@8708 2850 case VMEXIT_INTR:
kaf24@8708 2851 raise_softirq(SCHEDULE_SOFTIRQ);
kaf24@8708 2852 break;
kaf24@8708 2853
kaf24@10081 2854
kaf24@10081 2855 case VMEXIT_INVD:
kaf24@10081 2856 svm_vmexit_do_invd(vmcb);
kaf24@10081 2857 break;
kaf24@10081 2858
kaf24@8708 2859 case VMEXIT_GDTR_WRITE:
kaf24@8708 2860 printk("WRITE to GDTR\n");
kaf24@8708 2861 break;
kaf24@8708 2862
kaf24@8708 2863 case VMEXIT_TASK_SWITCH:
kaf24@8708 2864 __hvm_bug(&regs);
kaf24@8708 2865 break;
kaf24@8708 2866
kaf24@8708 2867 case VMEXIT_CPUID:
kaf24@8708 2868 svm_vmexit_do_cpuid(vmcb, regs.eax, &regs);
kaf24@8708 2869 break;
kaf24@8708 2870
kaf24@8708 2871 case VMEXIT_HLT:
kaf24@8708 2872 svm_vmexit_do_hlt(vmcb);
kaf24@8708 2873 break;
kaf24@8708 2874
kaf24@8708 2875 case VMEXIT_INVLPG:
kaf24@8708 2876 svm_handle_invlpg(0, &regs);
kaf24@8708 2877 break;
kaf24@8708 2878
kaf24@8708 2879 case VMEXIT_INVLPGA:
kaf24@8708 2880 svm_handle_invlpg(1, &regs);
kaf24@8708 2881 break;
kaf24@8708 2882
kaf24@8708 2883 case VMEXIT_VMMCALL:
kaf24@8708 2884 svm_do_vmmcall(v, &regs);
kaf24@8708 2885 break;
kaf24@8708 2886
kaf24@8708 2887 case VMEXIT_CR0_READ:
kaf24@8708 2888 svm_cr_access(v, 0, TYPE_MOV_FROM_CR, &regs);
kaf24@8708 2889 break;
kaf24@8708 2890
kaf24@8708 2891 case VMEXIT_CR2_READ:
kaf24@8708 2892 svm_cr_access(v, 2, TYPE_MOV_FROM_CR, &regs);
kaf24@8708 2893 break;
kaf24@8708 2894
kaf24@8708 2895 case VMEXIT_CR3_READ:
kaf24@8708 2896 svm_cr_access(v, 3, TYPE_MOV_FROM_CR, &regs);
kaf24@8708 2897 break;
kaf24@8708 2898
kaf24@8708 2899 case VMEXIT_CR4_READ:
kaf24@8708 2900 svm_cr_access(v, 4, TYPE_MOV_FROM_CR, &regs);
kaf24@8708 2901 break;
kaf24@8708 2902
kaf24@8708 2903 case VMEXIT_CR8_READ:
kaf24@8708 2904 svm_cr_access(v, 8, TYPE_MOV_FROM_CR, &regs);
kaf24@8708 2905 break;
kaf24@8708 2906
kaf24@8708 2907 case VMEXIT_CR0_WRITE:
kaf24@8708 2908 svm_cr_access(v, 0, TYPE_MOV_TO_CR, &regs);
kaf24@8708 2909 break;
kaf24@8708 2910
kaf24@8708 2911 case VMEXIT_CR2_WRITE:
kaf24@8708 2912 svm_cr_access(v, 2, TYPE_MOV_TO_CR, &regs);
kaf24@8708 2913 break;
kaf24@8708 2914
kaf24@8708 2915 case VMEXIT_CR3_WRITE:
kaf24@8708 2916 svm_cr_access(v, 3, TYPE_MOV_TO_CR, &regs);
kaf24@8895 2917 local_flush_tlb();
kaf24@8708 2918 break;
kaf24@8708 2919
kaf24@8708 2920 case VMEXIT_CR4_WRITE:
kaf24@8708 2921 svm_cr_access(v, 4, TYPE_MOV_TO_CR, &regs);
kaf24@8708 2922 break;
kaf24@8708 2923
kaf24@8708 2924 case VMEXIT_CR8_WRITE:
kaf24@8708 2925 svm_cr_access(v, 8, TYPE_MOV_TO_CR, &regs);
kaf24@8708 2926 break;
kaf24@8708 2927
kaf24@8708 2928 case VMEXIT_DR0_READ:
kaf24@8708 2929 svm_dr_access(v, 0, TYPE_MOV_FROM_DR, &regs);
kaf24@8708 2930 break;
kaf24@8708 2931
kaf24@8708 2932 case VMEXIT_DR1_READ:
kaf24@8708 2933 svm_dr_access(v, 1, TYPE_MOV_FROM_DR, &regs);
kaf24@8708 2934 break;
kaf24@8708 2935
kaf24@8708 2936 case VMEXIT_DR2_READ:
kaf24@8708 2937 svm_dr_access(v, 2, TYPE_MOV_FROM_DR, &regs);
kaf24@8708 2938 break;
kaf24@8708 2939
kaf24@8708 2940 case VMEXIT_DR3_READ:
kaf24@8708 2941 svm_dr_access(v, 3, TYPE_MOV_FROM_DR, &regs);
kaf24@8708 2942 break;
kaf24@8708 2943
kaf24@8708 2944 case VMEXIT_DR6_READ:
kaf24@8708 2945 svm_dr_access(v, 6, TYPE_MOV_FROM_DR, &regs);
kaf24@8708 2946 break;
kaf24@8708 2947
kaf24@8708 2948 case VMEXIT_DR7_READ:
kaf24@8708 2949 svm_dr_access(v, 7, TYPE_MOV_FROM_DR, &regs);
kaf24@8708 2950 break;
kaf24@8708 2951
kaf24@8708 2952 case VMEXIT_DR0_WRITE:
kaf24@8708 2953 svm_dr_access(v, 0, TYPE_MOV_TO_DR, &regs);
kaf24@8708 2954 break;
kaf24@8708 2955
kaf24@8708 2956 case VMEXIT_DR1_WRITE:
kaf24@8708 2957 svm_dr_access(v, 1, TYPE_MOV_TO_DR, &regs);
kaf24@8708 2958 break;
kaf24@8708 2959
kaf24@8708 2960 case VMEXIT_DR2_WRITE:
kaf24@8708 2961 svm_dr_access(v, 2, TYPE_MOV_TO_DR, &regs);
kaf24@8708 2962 break;
kaf24@8708 2963
kaf24@8708 2964 case VMEXIT_DR3_WRITE:
kaf24@8708 2965 svm_dr_access(v, 3, TYPE_MOV_TO_DR, &regs);
kaf24@8708 2966 break;
kaf24@8708 2967
kaf24@8708 2968 case VMEXIT_DR6_WRITE:
kaf24@8708 2969 svm_dr_access(v, 6, TYPE_MOV_TO_DR, &regs);
kaf24@8708 2970 break;
kaf24@8708 2971
kaf24@8708 2972 case VMEXIT_DR7_WRITE:
kaf24@8708 2973 svm_dr_access(v, 7, TYPE_MOV_TO_DR, &regs);
kaf24@8708 2974 break;
kaf24@8708 2975
kaf24@8708 2976 case VMEXIT_IOIO:
kaf24@10763 2977 svm_io_instruction(v);
kaf24@8708 2978 break;
kaf24@8708 2979
kaf24@8708 2980 case VMEXIT_MSR:
kaf24@8708 2981 svm_do_msr_access(v, &regs);
kaf24@8708 2982 break;
kaf24@8708 2983
kaf24@8708 2984 case VMEXIT_SHUTDOWN:
kaf24@8708 2985 printk("Guest shutdown exit\n");
kaf24@8708 2986 domain_crash_synchronous();
kaf24@8708 2987 break;
kaf24@8708 2988
kaf24@8708 2989 default:
kaf24@8708 2990 printk("unexpected VMEXIT: exit reason = 0x%x, exitinfo1 = %llx, "
kaf24@8708 2991 "exitinfo2 = %llx\n", exit_reason,
kaf24@8708 2992 (unsigned long long)vmcb->exitinfo1,
kaf24@8708 2993 (unsigned long long)vmcb->exitinfo2);
kaf24@8708 2994 __hvm_bug(&regs); /* should not happen */
kaf24@8708 2995 break;
kaf24@8708 2996 }
kaf24@8708 2997
kaf24@8708 2998 #ifdef SVM_EXTRA_DEBUG
kaf24@8708 2999 if (do_debug)
kaf24@8708 3000 {
kaf24@8708 3001 printk("%s: Done switch on vmexit_code\n", __func__);
kaf24@8708 3002 svm_dump_regs(__func__, &regs);
kaf24@8708 3003 }
kaf24@8708 3004
kaf24@8708 3005 if (do_debug)
kaf24@8708 3006 {
kaf24@8708 3007 printk("vmexit_handler():- guest_table = 0x%08x, "
kaf24@8708 3008 "monitor_table = 0x%08x, shadow_table = 0x%08x\n",
kaf24@8708 3009 (int)v->arch.guest_table.pfn,
kaf24@8708 3010 (int)v->arch.monitor_table.pfn,
kaf24@8708 3011 (int)v->arch.shadow_table.pfn);
kaf24@8708 3012 printk("svm_vmexit_handler: Returning\n");
kaf24@8708 3013 }
kaf24@8708 3014 #endif
kaf24@8708 3015
kaf24@8708 3016 return;
kaf24@8708 3017 }
kaf24@8708 3018
kaf24@8708 3019 asmlinkage void svm_load_cr2(void)
kaf24@8708 3020 {
kaf24@8708 3021 struct vcpu *v = current;
kaf24@8708 3022
kaf24@8708 3023 local_irq_disable();
kaf24@9948 3024 asm volatile("mov %0,%%cr2": :"r" (v->arch.hvm_svm.cpu_cr2));
kaf24@8708 3025 }
kaf24@8708 3026
kaf24@8708 3027 asmlinkage void svm_asid(void)
kaf24@8708 3028 {
kaf24@8708 3029 struct vcpu *v = current;
kaf24@8708 3030 struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
kaf24@9061 3031
kaf24@9061 3032 /*
kaf24@9061 3033 * if need to assign new asid, or if switching cores,
kaf24@9061 3034 * retire asid for the old core, and assign a new asid to the current core.
kaf24@9061 3035 */
kaf24@9061 3036 if ( test_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags ) ||
kaf24@9061 3037 ( v->arch.hvm_svm.asid_core != v->arch.hvm_svm.launch_core )) {
kaf24@9061 3038 /* recycle asid */
kaf24@9061 3039 if ( !asidpool_assign_next( vmcb, 1,
kaf24@9061 3040 v->arch.hvm_svm.asid_core, v->arch.hvm_svm.launch_core )) {
kaf24@8894 3041 /* If we get here, we have a major problem */
kaf24@8894 3042 domain_crash_synchronous();
kaf24@8708 3043 }
kaf24@9061 3044
kaf24@9061 3045 v->arch.hvm_svm.asid_core = v->arch.hvm_svm.launch_core;
kaf24@9061 3046 clear_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags );
kaf24@8708 3047 }
kaf24@10084 3048
kaf24@10084 3049 /* make sure the HSA is set for the current core */
kaf24@10084 3050 set_hsa_to_guest( &v->arch.hvm_svm );
kaf24@8708 3051 }
kaf24@8708 3052
kaf24@8708 3053 /*
kaf24@8708 3054 * Local variables:
kaf24@8708 3055 * mode: C
kaf24@8708 3056 * c-set-style: "BSD"
kaf24@8708 3057 * c-basic-offset: 4
kaf24@8708 3058 * tab-width: 4
kaf24@8708 3059 * indent-tabs-mode: nil
kaf24@8708 3060 * End:
kaf24@8708 3061 */