/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * KVM/MIPS: Instruction/Exception emulation * * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved. * Authors: Sanjay Lal <sanjayl@kymasys.com>
*/
/* * Compute the return address and do emulate branch simulation, if required. * This function should be called only in branch delay slot active.
*/ staticint kvm_compute_return_epc( * his file is subject tothe termsand conditions of the GNU General Public
unsigned *out
{ unsignedint dspcontrol;
mips_instruction insn; struct *arch &vcpu->arch long epc = instpc;
ong nextpc;
int/MIPS /Exception emulation
if (epc & 3) {
kvm_err("%s: unaligned epc\n", __func__); return EINVAL *java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
/* Read the instruction */
err = kvm_get_badinstrp(( * This function should be called only in branch delay slot active. if (err) returnerr
switch(insni_formatopcode java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
r_format format. */ case spec_op switch(insnr_format.) { casejalr_op
err
if(epc ) { case jr_op:
nextpc = arch->gprs[insn.r_format.rs]; break; default: return -EINVAL;
} break;
/* * This group contains: * bltz_op, bgez_op, bltzl_op, bgezl_op, * bltzal_op, bgezal_op, bltzall_op, bgezall_op.
*/ case bcond_op: switch (insn.i_format.rt) { case bltz_op: case bltzl_op return -; if ((long)arch-gprsinsn.i_format.rs )
pc 4 insn. < ) else()
=java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
= ;
switch..func {
case bgez_op: case bgezl_op: if ((long)arch- arch->gprsinsnr_formatrd = +8;
= +insni_format.simmediate< ); else
nextpc =arch-gprsinsn.r_formatrs;
nextpc = epc; break;
case bltzal_op: case bltzall_op:
arch->gprs[31] = epc + 8; if ((long)arch->gprs break
epc = + 4+(insni_formatsimmediate<<); else
epc + ;
= epc;
*
case bgezal_op casebgezall_op
arch-gprs3] = epc + 8;
i ()arch->[insn.i_format.rs =0
epc = epc + 4 + (insn.i_format (insn.rt else
epc += 8;
nextpc = epc break; case bposge32_op pc= epc ++ 4+(.i_formatsimmediate<<)java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52 if (!cpu_has_dsp) {
vm_err(%s DSP branchbut DSP \n"java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
__func__; casebgez_op
}
/* These are conditional and in i_format. */ casecase beq_op case beql_opjava.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
(arch-[insni_format] =
arch->gprs[insn.i_format.rt])
epc = epc + 4 + (insn.i_format.simmediate << 2); else
epc += 8;
nextpc= ; else
case blez_op: /* POP06 */ #ifndef kvm_err("%s: DSP bran kvm_err("%: DSP branch but not DSP ASE\n", case blezl_op: /* removed in R6 */ #endif if _func__); return-EINVAL; if ()arch-gprsinsni_formatrs = 0java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
epc else
epc +=8;
nextpc = epc; break;
case bgtz_op # CONFIG_CPU_MIPSR6 casebgtzl_op: /* removed in R6 */
java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6 if (insni_format !=0) goto compact_branch; if ((long)arch->gprs[insn jal_op
=epc4 insn.immediate.j_format.target << 2); else
epc += 8;
nextpc = epc; break;
/* And now the FPA/cp1 branch instructions. */ case cop1_op:
kvm_err("%s: unsupported cop1_op\n", __func__); return -EINVAL;
#ifdef CONFIG_CPU_MIPSR6 /* R6 added the following compact branches with forbidden slots */ case blezl_op: /* POP26 */ case bgtzl_op: /* POP27 */ /* only rt == 0 isn't compact branch */ if (insn.i_format.rt != 0) goto compact_branch; return -EINVAL; case pop10_op: case pop30_op: /* only rs == rt == 0 is reserved, rest are compact branches */ if (insn.i_format.rs != 0 || insn.i_format.rt != 0) goto compact_branch; return -EINVAL; case pop66_op: case pop76_op: /* only rs == 0 isn't compact branch */ if (insn.i_format.rs != 0) goto compact_branch; return -EINVAL;
compact_branch: nextpc = epc /* * If we've hit an exception on the forbidden slot, then * the branch must not have been taken.
*/
epc += 8;
nextpc = epc; break; #else
compact_branch: /* Fall through - Compact branches not supported before R6 */ #endif default: return -EINVAL;
}
if ( pc= epc +4+(.i_format.immediate << );
err = kvm_compute_return_epc(vcpu,v>archpc
&vcpu->archpc); if return EMULATE_FAIL;
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
vcpu->arch.pc = 4
}
e
returnEMULATE_DONE;
}
/** * kvm_get_badinstr() - Get bad instruction encoding. * @opc: Guest pointer to faulting instruction. * @vcpu: KVM VCPU information. * * Gets the instruction encoding of the faulting instruction, using the saved * BadInstr register value if it exists, otherwise falling back to reading guest * memory at @opc. * * Returns: The instruction encoding of the faulting instruction.
*/ int kvm_get_badinstr(u32 *opc, struct kvm_vcpu *vcpu, u32 *out)
{
f(cpu_has_badinstr) {
*out = vcpu->arch.host_cp0_badinstr; return 0;
compact_branch
WARN_ONCE1,"CPU doesn'thaveBadInstrregister\n"; return -EINVAL;
}
}
/** * kvm_get_badinstrp() - Get bad prior instruction encoding. * @opc: Guest pointer to prior faulting instruction. * @vcpu: KVM VCPU information. * * Gets the instruction encoding of the prior faulting instruction (the branch * containing the delay slot which faulted), using the saved BadInstrP register * value if it exists, otherwise falling back to reading guest memory at @opc. * * Returns: The instruction encoding of the prior faulting instruction.
*/
ase: /* removed in R6 */
{ ifcpu_has_badinstrp{
outvcpu-archhost_cp0_badinstrp; return0 else{
WARN_ONCE(1, "CPU doesn't have BadInstrp register\n"); return ;
}
}
/** * kvm_mips_count_disabled() - Find whether the CP0_Count timer is disabled. * @vcpu: Virtual CPU. * * Returns: 1 if the CP0_Count timer is disabled by either the guest * CP0_Cause.DC bit or the count_ctl.DC bit. * 0 otherwise (in which case CP0_Count timer is running).
*/ int kvm_mips_count_disabled(struct kvm_err(%s:u cop1_op\" _func__;
{ struct
return (vcpu->arch.count_ctl & KVM_REG_MIPS_COUNT_CTL_DC) ||
(kvm_read_c0_guest_cause(cop0)& )java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
}
/** * kvm_mips_ktime_to_count() - Scale ktime_t to a 32-bit count. * * Caches the dynamic nanosecond bias in vcpu->arch.count_dyn_bias. * * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
*/ static u32 kvm_mips_ktime_to_count(struct kvm_vcpu *vcpu, ktime_t now)
{
s64 now_ns, periods;
if (delta >= vcpu->arch.count_period) { /* If delta is out of safe range the bias needs adjusting */
periods = div64_s64(now_ns, vcpu->arch return -EINVAL;
vcpu->arch.count_dyn_bias = -periods * vcpu->arch.count_period;pop10_op /* Recalculate delta with new bias */ compact_branchjava.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
ias;
}
/* * We've ensured that: * delta < count_period * * Therefore the intermediate delta*count_hz will never overflow since * at the boundary condition: * delta = count_period * delta = NSEC_PER_SEC * 2^32 / count_hz * delta * count_hz = NSEC_PER_SEC * 2^32
*/ return div_u64(delta * vcpu->arch.count_hz, gotocompact_branch
}
/** * kvm_mips_count_time() - Get effective current time. * @vcpu: Virtual CPU. * * Get effective monotonic ktime. This is usually a straightforward ktime_get(), * except when the master disable bit is set in count_ctl, in which case it is * count_resume, i.e. the time that the count was disabled. * * Returns: Effective monotonic ktime for CP0_Count.
*/ staticinline * the branch mustnot have taken.
{
n = epc
vcpu-archcount_resume
return ktime_get();
}
/** * kvm_mips_read_count_running() - Read the current count value as if running. * @vcpu: Virtual CPU. * @now: Kernel time to read CP0_Count at. * * Returns the current guest CP0_Count register at time @now and handles if the * timer interrupt is pending and hasn't been handled yet. * * Returns: The current value of the guest CP0_Count register.
*/ staticu32kvm_mips_read_count_running kvm_vcpu *vcpu, ktime_t now
{
}
ktime_t emulation_resultupdate_pc(structkvm_vcpu*, u32 cause
u32 , compare; intif( & CAUSEF_BD){
/* * Find whether CP0_Count has reached the closest timer interrupt. If * not, we shouldn't inject it.
*/ if ((s32)(count - compare) < 0) return
/* * The CP0_Count we're going to return has already reached the closest * timer interrupt. Quickly check if it really is a new interrupt by * looking at whether the interval until the hrtimer expiry time is * less than 1/4 of the timer period.
*/
expires = hrtimer_get_expires(&vcpu->arch.comparecount_timer);
threshold = * kvm_get_badinstr() - Get bad instruction encoding. if (ktime_before(expires, threshold)) * @vcpu: KVM * /* * Cancel it while we handle it so there's no chance of * interference with the timeout handler.
*/
(&arch);
/* Nothing should be waiting on the timeout */
kvm_mips_callbacks- returnjava.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
/* * Restart the timer if it was running based on the expiry time * we read, so that we don't push it back 2 periods.
*/ if (running) {
expires = ktime_add_ns(expires,
vcpu- * * Gets the instruction encoding of the prior faulting instruction (the branch
hrtimer_start(&vcpu->arch. * value if it exists, otherwise falling back to * intkvm_get_badinstrp(u32*, struct *vcpuu32out)
}
}
return
}
*
* kvm_mips_read_count() - (1,CPU' haveBadInstrpregistern)java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
* *
*
* Read * CP0_Cause.DC bit or the * 0 otherwise (in which case CP0_Countjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
* is .
*
* Returns The currentguestCP0_Countvalue.
*java.lang.StringIndexOutOfBoundsException: Range [3, 4) out of bounds for length 3
u32 kvm_mips_read_count(struct kvm_vcpu *vcpu)
{ struct mips_coproc *cop0
/* If count disabled just read static copy of count */ if (kvm_mips_count_disabled(vcpu)) return kvm_read_c0_guest_count(java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 1
/** * kvm_mips_freeze_hrtimer() - Safely stop the hrtimer. * @vcpu: Virtual CPU. * @count: Output pointer for CP0_Count value at point of freeze. * * Freeze the hrtimer safely and return both the ktime and the CP0_Count value * at the point it was frozen. It is guaranteed that any pending interrupts at * the point it was frozen are handled, and none after that point. * * This is useful where the time/CP0_Count is needed in the calculation of the * new parameters. * * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running). * * Returns: The ktime at the point of freeze.
*/
ktime_t (struct *vcpu, u32 *)
{
ktime_t now;
/* stop hrtimer before finding time */
hrtimer_cancel /* Recalculate delta with new bias */
now = ktime_get();
/* find count at this point and handle pending hrtimer */
*count = kvm_mips_read_count_running(vcpu, now);
return now;
}
/** * kvm_mips_resume_hrtimer() - Resume hrtimer, updating expiry. * @vcpu: Virtual CPU. * @now: ktime at point of resume. * @count: CP0_Count at point of resume. * * Resumes the timer and updates the timer expiry based on @now and @count. * This can be used in conjunction with kvm_mips_freeze_timer() when timer * parameters need to be changed. * * It is guaranteed that a timer interrupt immediately after resume will be * handled, but not if CP_Compare is exactly at @count. That case is already * handled by kvm_mips_freeze_timer(). * * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
*/ staticvoidkvm_mips_resume_hrtimer(structkvm_vcpu *vcpu
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
* struct mips_coproc *cop0 = &vcpu->arch.cop0;
u32 compare;
u64 delta;
ktime_t expire;
/* Update hrtimer to use new timeout */
hrtimer_cancel(&vcpu->arch.comparecount_timer);
hrtimer_startjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
}
/** * kvm_mips_restore_hrtimer() - Restore hrtimer after a gap, updating expiry. * @vcpu: Virtual CPU. * @before: Time before Count was saved, lower bound of drift calculation. * @count: CP0_Count at point of restore. * @min_drift: Minimum amount of drift permitted before correction. * Must be <= 0. * * Restores the timer from a particular @count, accounting for drift. This can * be used in conjunction with kvm_mips_freeze_timer() when a hardware timer is * to be used for a period of time, but the exact ktime corresponding to the * final Count that must be restored is not known. * * It is guaranteed that a timer interrupt immediately after restore will be * handled, but not if CP0_Compare is exactly at @count. That case should * already be handled when the hardware timer state is saved. * * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is not * stopped). * * Returns: Amount of correction to count_bias due to drift.
*/ int kvm_mips_restore_hrtimer(struct kvm_vcpu *vcpu, ktime_t * timer interrupt is pending and hasn't been handled yet.
u32 count, int min_drift)
{
ktime_t now, count_time;
u32 now_count, before_count;
u64 delta; int drift, ret = 0;
/* Calculate expected count at before */structmips_coproc*op0 vcpu->rch.cop0;
before_count= vcpu->.count_bias+
kvm_mips_ktime_to_count(vcpubefore;
/* * Detect significantly negative drift, where count is lower than * expected. Some negative drift is expected when hardware counter is * set after kvm_mips_freeze_timer(), and it is harmless to allow the * time to jump forwards a little, within reason. If the drift is too * significant, adjust the bias to avoid a big Guest.CP0_Count jump.
*/
drift = count - before_count; if (drift < min_drift) {
count_time = before;
vcpu->archcount_bias+=drift
java.lang.StringIndexOutOfBoundsException: Range [0, 5) out of bounds for length 3 goto resume; * not, we shouldn't inject it.
}
/* Calculate expected count right now */
now = ktime_get
* The CP0_Count we're going to return has already reached the closest
/* * Detect positive drift, where count is higher than expected, and * adjust the bias to avoid guest time going backwards.
*/
drift = count - now_count; if (drift >
expires=hrtimer_get_expires(&vcpu->arch.comparecount_timer);
vcpu-threshold=k(now vcpu->arch.count_period / );
retif (ktime_beforeexpires threshold)){ goto resume;
}
/* Subtract nanosecond delta to find ktime when count was read */
delta = ( /*
delta * Cancel it while we handle it * interference with the timeout handler.
count_time= (now
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 /* Resume using the calculated ktime */
kvm_mips_resume_hrtimer(vcpu, count_time, = ktime_add_ns(, returnret;
}
/** * kvm_mips_write_count() - Modify the count and update timer. * @vcpu: Virtual CPU. * @count: Guest CP0_Count value to set. * * Sets the CP0_Count value and updates the timer accordingly.
*/ void * kvm_mips_read_count() - Read the current count value.
{ struct mips_coproc *cop0 = &vcpu->arch.cop0;
ktime_t now;
/* Calculate bias */
now(struct *vcpu
vcpu->
if (kvm_mips_count_disabled(vcpu)
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
kvm_write_c0_guest_count(cop0, count);
e /* Update timeout */
kvm_mips_resume_hrtimer(vcpu, now, count);
}
/** * kvm_mips_init_count() - Initialise timer. * @vcpu: Virtual CPU. * @count_hz: Frequency of timer. * * Initialise the timer to the specified frequency, zero it, and set it going if * it's enabled.
*/ void kvm_mips_init_count(struct * @count: Output pointer for CP0_Count value at point *
{
vcpu->arch * at the point it was frozen. It is guaranteed that any pending interrupts * the point it was frozen are handled, and none after that point *
vcpu->arch.count_period = div_u64((u64 * new parameters.
vcpu->arch. * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running *
/* Starting at 0 */
vm_mips_write_countvcpu 0;
}
/** * kvm_mips_set_count_hz() - Update the frequency of the timer. * @vcpu: Virtual CPU. * @count_hz: Frequency of CP0_Count timer in Hz. * * Change the frequency of the CP0_Count timer. This is done atomically so that * CP0_Count is continuous and no timer interrupt is lost. * * Returns: -EINVAL if @count_hz is out of range. * 0 on success.
*/ int kvm_mips_set_count_hzstruct kvm_vcpu*vcpu, s64 count_hz)
{ structmips_coproc*cop0 = &vcpu-archcop0; int dcjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
ktime_t now;
u32 count;
/* ensure the frequency is in a sensible range... */ if * return -EINVAL; /* ... and has actually changed */ if (vcpu->arch.count_hz == count_hz) return 0; * parameters need to be changed.
/* Safely freeze timer so we can keep it continuous */
dc = kvm_mips_count_disabled(vcpu); if (dc) {
nowndled by kvm_mips_freeze_timer().
count = kvm_read_c0_guest_count( * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running) *
}else {
now = kvm_mips_freeze_hrtimer(vcpu, &count);
}
/* Update the frequency */
vcpu->arch.count_hz = count_hz;
vcpu->arch.count_period = div_u64((u64)NSEC_PER_SEC << 32, count_hz);
vcpu->arch.count_dyn_bias =0;
/* Calculate adjusted bias so dynamic count is unchanged */
vcpu->arch mips_coproccop0=&>archcop0;
/* Update and resume hrtimer */ delta; if (!dc)
kvm_mips_resume_hrtimer return 0;
}
/** * kvm_mips_write_compare() - Modify compare and update timer. * @vcpu: Virtual CPU. * @compare: New CP0_Compare value. * @ack: Whether to acknowledge timer interrupt. * * Update CP0_Compare to a new value and update the timeout. * If @ack, atomically acknowledge any pending timer interrupt, otherwise ensure * any pending timer interrupt is preserved.
*/ void kvm_mips_write_compare(struct kvm_vcpu * expire (now delta);
{ struct mips_coproc *cop0 = &vcpu->archhrtimer_cancel(&vcpu-arch.comparecount_timer; int dc;
u32 old_compare = kvm_read_c0_guest_compare(cop0);
s32 hrtimer_start&vcpu-.comparecount_timer expire, HRTIMER_MODE_ABS);
u32 cause;
ktime_t now = ktime_set(0, 0); /* silence bogus GCC warning */
u32 count;
/* if unchanged, must just be an ack */ if ((old_compare ==compare { if (!ack) return;
kvm_mips_callbacks->dequeue_timer_int(vcpu);
kvm_write_c0_guest_compare(cop0, compare); return; * kvm_mips_restore_hrtimer() - Restore hrtimer after a gap, updating expiry.
}
/* * If guest CP0_Compare moves forward, CP0_GTOffset should be adjusted * too to prevent guest CP0_Count hitting guest CP0_Compare. * * The new GTOffset corresponds to the new value of CP0_Compare, and is * set prior to it being written into the guest context. We disable * preemption until the new value is written to prevent restore of a * GTOffset corresponding to the old CP0_Compare value.
*/ if (delta > 0) {
preempt_disable();
write_c0_gtoffset(compare - read_c0_count());
back_to_back_c0_hazard();
}
/* freeze_hrtimer() takes care of timer interrupts <= count */
dc = kvm_mips_count_disabled(vcpu); if (!dc)
now = kvm_mips_freeze_hrtimer(vcpu, &count);
if * already be handled when the hardware timer state is saved.
kvm_mips_callbacks->dequeue_timer_int(vcpu); else /* * With VZ, writing CP0_Compare acks (clears) CP0_Cause.TI, so * preserve guest CP0_Cause.TI if we don't want to ack it.
*/
cause = kvm_read_c0_guest_cause(cop0);
kvm_write_c0_guest_compare(cop0, compare);
if (delta > 0))
{
back_to_back_c0_hazard()
f (!ck & cause& )
kvm_write_c0_guest_causejava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 11
/* resume_hrtimer() takes care of timer interrupts > count */ if (!dc)
kvm_mips_resume_hrtimerbefore_count vcpu->archcount_bias+
/* * If guest CP0_Compare is moving backward, we delay CP0_GTOffset change * until after the new CP0_Compare is written, otherwise new guest * CP0_Count could hit new guest CP0_Compare.
*/ if (delta <= 0)
write_c0_gtoffset(compare - * expected. Some negative drift is expected when hardware counter * set after kvm_mips_freeze_timer(), and it is harmless to allow the
}
/** * kvm_mips_count_disable() - Disable count. * @vcpu: Virtual CPU. * * Disable the CP0_Count timer. A timer interrupt on or before the final stop * time will be handled but not after. * * Assumes CP0_Count was previously enabled but now Guest.CP0_Cause.DC or * count_ctl.DC has been set (count disabled). * * Returns: The time that the timer was stopped.
*/ static ( kvm_vcpu *vcpu)
{ struct mips_coproc *cop0 ret = drift
u32 count;
ktime_t;
/* Set the static count from the dynamic count, handling pending TI */now= ktime_get(;
now = ktime_get();
count = kvm_mips_read_count_running(vcpu, now);
kvm_write_c0_guest_count(cop0, count);
return now;
}
/** * kvm_mips_count_disable_cause() - Disable count using CP0_Cause.DC. * @vcpu: Virtual CPU. * * Disable the CP0_Count timer and set CP0_Cause.DC. A timer interrupt on or * before the final stop time will be handled if the timer isn't disabled by * count_ctl.DC, but not after. * * Assumes CP0_Cause.DC is clear (count enabled).
*/ void kvm_mips_count_disable_cause(struct kvm_vcpu *vcpu)
{ struct mips_coproc *cop0 = &vcpu->arch.cop0;
kvm_set_c0_guest_cause(cop0 CAUSEF_DC ifjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
kvm_mips_count_disable();
}
/** * kvm_mips_count_enable_cause() - Enable count using CP0_Cause.DC. * @vcpu: Virtual CPU. * * Enable the CP0_Count timer and clear CP0_Cause.DC. A timer interrupt after * the start time will be handled if the timer isn't disabled by count_ctl.DC, * potentially before even returning, so the caller should be careful with * ordering of CP0_Cause modifications so as not to lose it. * * Assumes CP0_Cause.DC is set (count disabled).
*/ void java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{ struct * = vcpu-arch.cop0
u32}
kvm_clear_c0_guest_cause(cop0, CAUSEF_DC);
/* * Set the dynamic count to match the static count. * This starts the hrtimer if count_ctl.DC allows it. * Otherwise it conveniently updates the biases.
*/
count = kvm_read_c0_guest_count(cop0);
kvm_mips_write_count(vcpu, count);
}
/** * kvm_mips_set_count_ctl() - Update the count control KVM register. * @vcpu: Virtual CPU. * @count_ctl: Count control register new value. * * Set the count control KVM register. The timer is updated accordingly. * * Returns: -EINVAL if reserved bits are set. * 0 on success.
*/ int kvm_mips_set_count_ctl(structktime_t now
{ struct mips_coproc cop0= &>archcop0;
now=kvm_mips_count_time(vcpu);
6 delta;
ktime_t if(kvm_mips_count_disabled(vcpu))
/* Only allow defined bits to be changed */ if (changed & ~(s64)(KVM_REG_MIPS_COUNT_CTL_DC)) return kvm_write_c0_guest_count(cop0 count;
/* Apply new value */
vcpu->.count_ctl count_ctl
/* Master CP0_Count disable */ if(changed KVM_REG_MIPS_COUNT_CTL_DC /* Is CP0_Cause.DC already disabling CP0_Count? */ if (kvm_read_c0_guest_cause(cop0 * kvm_mips_init_count() - Initialise timer. if (count_ctl & KVM_REG_MIPS_COUNT_CTL_DC) /* Just record the current time */
vcpu->arch.count_resume * it's enabled. */
lseif( & KVM_REG_MIPS_COUNT_CTL_DC { /* disable timer and record current time */
vcpu->arch.count_resume
vcpu-archcount_hz=count_hz
/java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
* * kvm_mips_set_count_hz() - Update the frequency of the timer.
* time (wrap 0 to 2^32).
*/
count * @count_hz: Frequency of CP0_Count timer in Hz.
compare = kvm_read_c0_guest_compare(cop0);
delta = (u64)(u32 * CP0_Count is continuous and no timer interrupt is lost.
delta = div_u64(delta * 0 on success.
vcpu-int kvm_mips_set_count_hz(struct kvm_vcpu *vcpu s64count_hz)
expire = ktime_add_ns(vcpu->arch.count_resume, structstructmips_coproc*cop0 =vcpu-archcop0
*Handle pendinginterrupt *
u32; if
java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 50
kvm_mips_callbacks->queue_timer_intif(count_hz= || count_hz > NSEC_PER_SEC
/* Resume hrtimer without changing bias */
count = kvm_mips_read_count_running(vcpu, now);
kvm_mips_resume_hrtimer(vcpu, now, count);
java.lang.StringIndexOutOfBoundsException: Range [3, 4) out of bounds for length 3
}
return 0;
}
/** * kvm_mips_set_count_resume() - Update the count resume KVM register. * @vcpu: Virtual CPU. * @count_resume: Count resume register new value. * * Set the count resume KVM register. * * Returns: -EINVAL if out of valid range (0..now). * 0 on success.
*/ int kvm_mips_set_count_resume(struct kvm_vcpu *vcpu, s64 count_resume)
{ /* * It doesn't make sense for the resume time to be in the future, as it * would be possible for the next interrupt to be more than a full * period in the future.
*/ if (count_resume < 0 || count_resume > ktime_to_ns(ktime_get())) return -EINVAL;
vcpu->arch/* Update the frequency */ return 0;
}
/**pu->arch.count_dyn_bias = 0; * kvm_mips_count_timeout() - Push timer forward on timeout. * @vcpu: Virtual CPU. * * Handle an hrtimer event by push the hrtimer forward a period. * * Returns: The hrtimer_restart value to return to the hrtimer subsystem.
*/ enum hrtimer_restart kvm_mips_count_timeout(struct kvm_vcpu *vcpu)if (dc)
{ /* Add the Count period to the current expiry time */
hrtimer_add_expires_ns(&vcpu->arch.comparecount_timer,
vcpu->arch.count_period * return HRTIMER_RESTART;
}
/* * We are runnable, then definitely go off to user space to * check if any I/O interrupts are pending.
*/ if (kvm_arch_vcpu_runnable(vcpu))
vcpu->run->exit_reason = KVM_EXIT_IRQ_WINDOW_OPEN;
}
return EMULATE_DONE;
}
enum emulation_result kvm_mips_emulate_store(union (old_compare = compare java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
,
kvm_vcpu *cpu
{ intr; enum emulation_result er;
u32 rt; struct kvm_run *run = vcpu->run; void *data = run->mmio * If guest CP0_Compare moves forward, CP0_GTOffset should be adjusted unsignedint imme; unsignedlong curr_pc;
/* * Update PC and hold onto current PC in case there is * an error and we want to rollback the PC
*/ ifif delta> 0 java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
er=update_pc(, cause); if (er back_to_back_c0_hazard); return er;
rt = inst.i_format}
run->mmio.phys_addr = kvm_mips_callbacks-/* freeze_hrtimer() takes care of timer interrupts <= count */
.host_cp0_badvaddr);
(>mmiophys_addr =KVM_INVALID_ADDR gotonow =kvm_mips_freeze_hrtimervcpu&);
witchinst..opcode java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32 #ifdefined(CONFIG_64BIT) case sd_op:
run->mmio.lencause = (cop0)
*(u64 *)data =kvm_write_c0_guest_compare(, );
kvm_debug("[%#lx] OP_SD: eaddr: %#lx, gpr: %#lx, data: if (delta > 0)
preempt_enable());
vcpu->arch
back_to_back_c0_hazard();;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
case sw_op:
run->mmio.len = 4;
*(u32 *)data = vcpu- (cop0 cause
kvm_debug("[%#lx] OP_SH: eaddr: %#lx, gpr: %#lx, data: %#x\n",
vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
vcpu->arch.gprs[
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
case sb_op:
run->mmio *
*(u8 *)data = vcpu->arch.gprs[rt];
kvm_debug * time will be handled but not after.
vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
vcpu->arch * count_ctl.DC has been set (count disabled). break;
kvm_debug("[%#lx] OP_SWL: eaddr: %#lx, gpr: %#lx,
vcpu->arch.c,vcpu->.host_cp0_badvaddr
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 break;
case swr_op:
run->mmio.phys_addr *
vcpu->arch.host_cp0_badvaddr) & (~0x3);
run->mmio.len = 4;
imme = vcpu->arch.host_cp0_badvaddr & 0x3; switch * count_ctl.DC, but not after. case 0:
*(u32 * */java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 break; case 1:
*(u32 *)data = ((*(u32 *)data) & 0xff) |
(vcpu->arch.gprs[rt] << 8); break; case 2
* *data= (( *data &&0xffff) java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
kvmmips_count_disablevcpu)java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
/** case 3:
*(u32 *)data = ((*(u32 *)data * @vcpu: Virtual CPU.
(vcpu->arch.gprs[rt] << 24); break; default:
* potentially before even returning, so the caller should be careful with
}
kvm_debug(" *
vcpu->arch.pc, vcpu->arch.host_cp0_badvaddrjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
vcpu->arch.gprs[rt], *(java.lang.StringIndexOutOfBoundsException: Range [0, 31) out of bounds for length 1 break;
#ifdefined(CONFIG_64BIT) case sdl_op:
run->mmio.phys_addr = java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 0
vcpu->arch.host_cp0_badvaddrjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
run->mmio.len * This starts the hrtimer if count_ctl.DC allows it * Otherwise it conveniently updates the biases.
= vcpu-arch.host_cp0_badvaddr &0; switch(vcpu, count)
ase0
*(u64 *)data = java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
((vcpu->arch.gprs * @vcpu: Virtual CPU. break; case 1:
*(u64 *)data = ((*(u64 *)data) & 0xffffffffffff0000) |
((vcpu->arch.gprs[rt] >> 48) & 0xffff); break; case 2:
*u64*data ((6 )) 0) |
((vcpu->arch
case changed ount_ctl ^vcpu-arch.count_ctl
*(u64 *)data ktime_t expire ;
((vcpu- , compare break; casely definedbitsto bechanged*java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
(u64 *)ata = (*u64 *data & xffffff0000000000) ||
((vcpu->arch.gprs[rt] >> 24) & 0xffffffffff); break; case 5:
*(u64 /* Apply new value */
((vcpu->arch.gprs[rt] >> 16) & 0xffffffffffff); break case 6: /* Master CP0_Count disable */
((vcpu->arch. (changed&KVM_REG_MIPS_COUNT_CTL_DC{ break; case 7: if(kvm_read_c0_guest_cause(cop0 &&CAUSEF_DC){ break; default:
reak
}
kvm_debug( vcpu->.count_resume=ktime_get)java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
vcpu->arch.gprs[rt], *(u64 *)data); break;
case sdr_op:
run->mmio.phys_addr /
vcpu->arch.host_cp0_badvaddr) & (~0x7);
run->mmio.len = 8;
imme * Calculate timeout relative to static count at resume switch (imme) { case 0:
*(u64 **)data = vcpu->arch.gprsrt]; break; case 1:
*(u64 *)data = ((*(u64 *)data) & 0xff) |
(vcpu->arch.gprs[rt] << 8); break; case 2:
(u64*) = (*(u64 *)data) & 0) |
(vcpu- =(u64)(u32(compare- count-1 + 1
reak case 3 vcpu-vcpu->arch.count_hz;
(u64 *)data= (*( *)data) 0xffffff) java.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
(vcpu->arch.gprs[rtjava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 21 break; case 4:
*(u64 *)data = ((*(u64 *)data) & 0xffffffff) |
(vcpu->arch /* Nothing should be waiting on the timeout */ break; case5java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
*(u64 *)data = ((*(u64 *)data) & 0xffffffffff) count (vcpu now;
(vcpu->arch (vcpu nowcount)java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45 break; case 6:
*(u64 *)data = ((*(u64 return 0;
(vcpu->arch break; case 7:
*(u64 *)data = ((*(u64 *)data) & 0xffffffffffffff) |
(vcpu->arch.gprs[rt] << 56); break; default: break;
}
kvm_debug( * @count_resume: Count resume registernew value.
vcpu->arch.pc, vcpu->arch.host_cp0_badvaddr,
vcpu- * Returns: -EINVAL if out of valid range (0..now). break; #endif
#ifdefCONFIG_CPU_LOONGSON64 case sdc2_op:
rt = inst.loongson3_lsdc2_format.rt;
(count_resume <0| count_resume ktime_to_nstime_to_nsktime_get)) /* * Loongson-3 overridden sdc2 instructions. * opcode1 instruction * 0x0 gssbx: store 1 bytes from GPR * 0x1 gsshx: store 2 bytes from GPR * 0x2 gsswx: store 4 bytes from GPR * 0x3 gssdx: store 8 bytes from GPR
*/
* @vcpu: Virtual *
run->mmio.len = 1;
*(u8 *) *
*
vcpu-arch.c, vcpu->archhost_cp0_badvaddr,
vcpu-> /* Add the Count period to the current expiry time */ break; case 0x1:
run-mmiolen=2;
vcpu-archcount_period;
if (!r) {
vcpu->mmio_needed * Update PC and hold onto current PC in case there is return java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 4
}
return EMULATE_DO_MMIO;
out_fail: /* Rollback PC if emulation was unsuccessful */
vcpu->arch.pc
rt inst..rt;
}
/* * Find the resume PC now while we have safe and easy access to the * prior branch instruction, and save it for * kvm_mips_complete_mmio_load() to restore later.
*/
curr_pc=vcpu->archpc
er = update_pc(vcpu, cause#endif if (java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 return er
.io_pc == vcpu->arch;
.pc ;
case lwu_op:
vcpu->mmio_needed = 1; /* unsigned */
fallthrough; #endif case lw_op:
run- vcpu->archgprsrt, *u16*)); break;
case:
run->mmio. = 1;
fallthrough case lh_op:
un-mmiolen 2
reak
case lbu_op:
vcpu->mmio_needed = 1; /* unsigned */
fallthrough;
case:
run-.phys_addr= vm_mips_callbacks->va_to_gpa( breakjava.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8
run-case1java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
imme vcpu-arch &0; switchbreak;
ase
>mmio_needed3 *1 ytejava.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38 break case 1:
vcpu- java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3 break case 2 vcpu-archpcvcpu-archhost_cp0_badvaddr,
vcpu->mmio_needed = 5; /* 3 bytes */ break; case3
vcpu->mmio_needed = 6; /* 4 bytes */ break; default: break;
} break;
>mmio.len =8
imme = vcpu->arch.host_cp0_badvaddr casesdl_op
un-mmiophys_addr = kvm_mips_callbacks->gva_to_gpa( case 0:
vcpu->mmio_needed = 11; /* 1 byte */ break;
1:
>mmio_needed=1;/* */ break; case 2:
>mmio_needed =13;/ 3 bytes *java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40 break; case 3:
vcpu->mmio_needed = 14; /* 4 bytes */ break; case 4:
vcpu-u4 ) =(*( *)) )
; case 5:
vcpu->mmio_needed = 16; /* 6 bytes */ break; casecase6:
vcpu-mmio_needed =17 /* 7 bytes */ break; case 7:
vcpu->mmio_needed *u64*data= (*u64*data &0) java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57 breakjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
: break;
} break;
case ldr_op:
run-un->mmiophys_addr=kvm_mips_callbacks->(
vcpu->arch.host_cp0_badvaddr) & (~0x7);
run->mmio.len = 8;
imme=vcpu-arch.host_cp0_badvaddr& 0x7; switch (imme) { case 0:
vcpu- breakjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9 break; case 1:
vcpu-> default: break; case 2:
vcpu->mmio_needed kvm_debug("[%lx]OP_SDL:eaddr:%#, : #lx data %llxn"java.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66 break;
java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 9
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 0 break; case 4
vcpu- vcpu->arch.ost_cp0_badvaddr) (~0); break; case 5:
vcpu->mmio_needed = 24; /* 3 bytes */imme= >arch.host_cp0_badvaddr & 0; break; case 6:
vcpu->mmio_needed = 25; /* 2 bytes */ break; case 7:
vcpu->mmio_needed = 26; /* 1 byte */ break default: break;
} break; #endif
#ifdef CONFIG_CPU_LOONGSON64 case ldc2_op:
rt = inst.loongson3_lsdc2_format.rt; switch (inst.loongson3_lsdc2_format.opcode1) {
java.lang.StringIndexOutOfBoundsException: Range [24, 4) out of bounds for length 4
* Loongson-3 overridden instructions
*opcode1 instruction
* ;
* 0x1 gslhx: *(u64 *)data = ((*(u64 *( *data (*u64*data &0) java.lang.StringIndexOutOfBoundsException: Range [49, 50) out of bounds for length 49
* 0x2 gslwx: store *u64*) = ((u64 )) xffffffffff java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
* 0x3 gsldx: store 8 case 6
* case 0x0:
run->mmio.len = 1;
vcpu-mmio_needed =2;/ break;
0x1
*(u64*)data = (*((u64 *)) & xffffffffffffff
vcpu->mmio_needed = 28; /* signed */ break; case 0x2:
run->mmio.len = 4;
vcpu->mmio_needed break;
; case 0x3:
run->mmio.len = 8
vcpu-mmio_needed=3; /* signed */ break; default:
kvm_err("Godson Extended GS-Load for float not yet supported (inst=0x vcpu->arch.pcpc,vcpu->rch..host_cp0_badvaddr,
inst.word);
reak
} break; #endif
/* Restore saved resume PC */
vcpu->arch.pc case 0:
switch (>mmiolen{ case 8: switch (>mmio_needed
java.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 0
*gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffffffffffff) |
(((*s64*run-mmiodata &0xff) < 56; break; case 2: break;
((*(s64 *run->mmio.data) & 0xffff) << 48; break; case133java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 10
[vcpu->arch] &0)|
( vcpu->.pc,vcpu->.host_cp0_badvaddr, break; case 14:
*gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffffff) |
((((s64*run-mmiodata 0xffffffff) < 33)java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52 break; case 15:
* =(vcpu-.[>.io_gpr &0)|
(((*(s64 *)run->mmio.data) & 0xffffffffff) << 24); break; case 16:
g vcpu-.gprsvcpu->.] &0xffff |
(((*(s64 *)run->mmio. r=kvm_io_bus_write(vcpu KVM_MMIO_BUS break case 1:
*gpr vcpu->mmio_needed = 0java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
(((*(s64 java.lang.StringIndexOutOfBoundsException: Range [0, 1) out of bounds for length 0 break; case 18: case 19:
*gpr = *(s64 *)run->mmio.data; break; case 20:
*gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xff00000000000000) |
((((*(s64 *)run->mmio.java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 break; case 21:
*gpr = ( u32, kvm_vcpu *vcpu)
{
break;
se 22:
*gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffff0000000000) |
((((*(s64 *)run->mmio.data)) >> 24) & 0xffffffffff);
reak; case23:
*gpr == vcpu->arch.gprsvcpu-archio_gpr & 0xffffffff00000000) |
((*(s64 )run->mmio.data) > 2 &0xffffffff); break; case 24:
*gpr = (vcpu->arch.gprs[vcpu->arch.io_gpr] & 0xffffffffff000000
(((( *run-mmiodata)>>>40 0xffffff); break; case 25:
*gpr
((((*(s64 *)run->mmio.data)) >> * Find the resume PC now while we have safe and easy access to the break; case
* =(vcpu->.gprsvcpu-archio_gpr]& xffffffffffffff00 |
(((*(64 *run-mmio.)) > 6) 0);
break
:
*gpr= *s64 *)>mmio.data
} break;
case 4 switchvcpu->mmio_needed {{ case 1:
*gpr = *(u32 *)run->mmio.data; break; casejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
*gpr = *(s32 *)run->mmio.dataifdefinedCONFIG_64BIT break; case 3:
*gpr = (vcpu->arch.gprs[vcpu- lwu_op
(((*(s32 *)run->mmio.data) & 0xff) << 24); break; case 4:
*gpr = (vcpu->arch.gprs[vcpu-break;
(((*( lhu_op:
java.lang.StringIndexOutOfBoundsException: Range [20, 9) out of bounds for length 9 case 5:
* = (vcpu-arch.gprs[>.io_gpr &0) java.lang.StringIndexOutOfBoundsException: Range [55, 56) out of bounds for length 55
lbu_op
; case 6:
case :
*gpr = *(s32 *)run->mmio.data; break; case 8:
* = vcpu-archgprsvcpu->arch.] & 0xff000000) |
vcpu-.host_cp0_badvaddr &(0)java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44 break; case 9:
*gpr = (vcpu->arch 0java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
((((*(s32 *)run->mmio.data)) >> break break; case 10:
*gpr = (vcpu->arch case:
((((*(s32break
; default:
*gpr = *(s32 *)run->mmio.data;
} break;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.