arch/x86/kvm/smm.c

Source file repositories/reference/linux-study-clean/arch/x86/kvm/smm.c

File Facts

System
Linux kernel
Corpus path
arch/x86/kvm/smm.c
Extension
.c
Size
19251 bytes
Lines
664
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (pcid) {
			bad = kvm_set_cr3(vcpu, cr3 | pcid);
			if (bad)
				return X86EMUL_UNHANDLEABLE;
		}

	}

	return X86EMUL_CONTINUE;
}

static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt,
			     const struct kvm_smram_state_32 *smstate)
{
	struct kvm_vcpu *vcpu = ctxt->vcpu;
	struct desc_ptr dt;
	int i, r;

	ctxt->eflags =  smstate->eflags | X86_EFLAGS_FIXED;
	ctxt->_eip =  smstate->eip;

	for (i = 0; i < 8; i++)
		*reg_write(ctxt, i) = smstate->gprs[i];

	if (kvm_set_dr(vcpu, 6, smstate->dr6))
		return X86EMUL_UNHANDLEABLE;
	if (kvm_set_dr(vcpu, 7, smstate->dr7))
		return X86EMUL_UNHANDLEABLE;

	rsm_load_seg_32(vcpu, &smstate->tr, smstate->tr_sel, VCPU_SREG_TR);
	rsm_load_seg_32(vcpu, &smstate->ldtr, smstate->ldtr_sel, VCPU_SREG_LDTR);

	dt.address =               smstate->gdtr.base;
	dt.size =                  smstate->gdtr.limit;
	kvm_x86_call(set_gdt)(vcpu, &dt);

	dt.address =               smstate->idtr.base;
	dt.size =                  smstate->idtr.limit;
	kvm_x86_call(set_idt)(vcpu, &dt);

	rsm_load_seg_32(vcpu, &smstate->es, smstate->es_sel, VCPU_SREG_ES);
	rsm_load_seg_32(vcpu, &smstate->cs, smstate->cs_sel, VCPU_SREG_CS);
	rsm_load_seg_32(vcpu, &smstate->ss, smstate->ss_sel, VCPU_SREG_SS);

	rsm_load_seg_32(vcpu, &smstate->ds, smstate->ds_sel, VCPU_SREG_DS);
	rsm_load_seg_32(vcpu, &smstate->fs, smstate->fs_sel, VCPU_SREG_FS);
	rsm_load_seg_32(vcpu, &smstate->gs, smstate->gs_sel, VCPU_SREG_GS);

	vcpu->arch.smbase = smstate->smbase;

	r = rsm_enter_protected_mode(vcpu, smstate->cr0,
					smstate->cr3, smstate->cr4);

	if (r != X86EMUL_CONTINUE)
		return r;

	kvm_x86_call(set_interrupt_shadow)(vcpu, 0);
	ctxt->interruptibility = (u8)smstate->int_shadow;

	return r;
}

#ifdef CONFIG_X86_64
static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt,
			     const struct kvm_smram_state_64 *smstate)
{
	struct kvm_vcpu *vcpu = ctxt->vcpu;
	struct desc_ptr dt;
	int i, r;

	for (i = 0; i < 16; i++)
		*reg_write(ctxt, i) = smstate->gprs[15 - i];

	ctxt->_eip   = smstate->rip;
	ctxt->eflags = smstate->rflags | X86_EFLAGS_FIXED;

	if (kvm_set_dr(vcpu, 6, smstate->dr6))
		return X86EMUL_UNHANDLEABLE;
	if (kvm_set_dr(vcpu, 7, smstate->dr7))
		return X86EMUL_UNHANDLEABLE;

	vcpu->arch.smbase =         smstate->smbase;

	if (__kvm_emulate_msr_write(vcpu, MSR_EFER, smstate->efer & ~EFER_LMA))
		return X86EMUL_UNHANDLEABLE;

	rsm_load_seg_64(vcpu, &smstate->tr, VCPU_SREG_TR);

	dt.size =                   smstate->idtr.limit;
	dt.address =                smstate->idtr.base;

Annotation

Implementation Notes