Merge commit 'v2.6.31-rc7' into x86/cleanups
Merge reason: we were on -rc1 before - go up to -rc7 Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
@@ -104,6 +104,9 @@ static s64 __kpit_elapsed(struct kvm *kvm)
|
||||
ktime_t remaining;
|
||||
struct kvm_kpit_state *ps = &kvm->arch.vpit->pit_state;
|
||||
|
||||
if (!ps->pit_timer.period)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The Counter does not stop when it reaches zero. In
|
||||
* Modes 0, 1, 4, and 5 the Counter ``wraps around'' to
|
||||
|
@@ -489,16 +489,20 @@ static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int lpage)
|
||||
*
|
||||
* If rmapp bit zero is one, (then rmap & ~1) points to a struct kvm_rmap_desc
|
||||
* containing more mappings.
|
||||
*
|
||||
* Returns the number of rmap entries before the spte was added or zero if
|
||||
* the spte was not added.
|
||||
*
|
||||
*/
|
||||
static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
|
||||
static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
|
||||
{
|
||||
struct kvm_mmu_page *sp;
|
||||
struct kvm_rmap_desc *desc;
|
||||
unsigned long *rmapp;
|
||||
int i;
|
||||
int i, count = 0;
|
||||
|
||||
if (!is_rmap_pte(*spte))
|
||||
return;
|
||||
return count;
|
||||
gfn = unalias_gfn(vcpu->kvm, gfn);
|
||||
sp = page_header(__pa(spte));
|
||||
sp->gfns[spte - sp->spt] = gfn;
|
||||
@@ -515,8 +519,10 @@ static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
|
||||
} else {
|
||||
rmap_printk("rmap_add: %p %llx many->many\n", spte, *spte);
|
||||
desc = (struct kvm_rmap_desc *)(*rmapp & ~1ul);
|
||||
while (desc->shadow_ptes[RMAP_EXT-1] && desc->more)
|
||||
while (desc->shadow_ptes[RMAP_EXT-1] && desc->more) {
|
||||
desc = desc->more;
|
||||
count += RMAP_EXT;
|
||||
}
|
||||
if (desc->shadow_ptes[RMAP_EXT-1]) {
|
||||
desc->more = mmu_alloc_rmap_desc(vcpu);
|
||||
desc = desc->more;
|
||||
@@ -525,6 +531,7 @@ static void rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn, int lpage)
|
||||
;
|
||||
desc->shadow_ptes[i] = spte;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void rmap_desc_remove_entry(unsigned long *rmapp,
|
||||
@@ -754,6 +761,19 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp)
|
||||
return young;
|
||||
}
|
||||
|
||||
#define RMAP_RECYCLE_THRESHOLD 1000
|
||||
|
||||
static void rmap_recycle(struct kvm_vcpu *vcpu, gfn_t gfn, int lpage)
|
||||
{
|
||||
unsigned long *rmapp;
|
||||
|
||||
gfn = unalias_gfn(vcpu->kvm, gfn);
|
||||
rmapp = gfn_to_rmap(vcpu->kvm, gfn, lpage);
|
||||
|
||||
kvm_unmap_rmapp(vcpu->kvm, rmapp);
|
||||
kvm_flush_remote_tlbs(vcpu->kvm);
|
||||
}
|
||||
|
||||
int kvm_age_hva(struct kvm *kvm, unsigned long hva)
|
||||
{
|
||||
return kvm_handle_hva(kvm, hva, kvm_age_rmapp);
|
||||
@@ -1407,24 +1427,25 @@ static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp)
|
||||
*/
|
||||
void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages)
|
||||
{
|
||||
int used_pages;
|
||||
|
||||
used_pages = kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages;
|
||||
used_pages = max(0, used_pages);
|
||||
|
||||
/*
|
||||
* If we set the number of mmu pages to be smaller be than the
|
||||
* number of actived pages , we must to free some mmu pages before we
|
||||
* change the value
|
||||
*/
|
||||
|
||||
if ((kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages) >
|
||||
kvm_nr_mmu_pages) {
|
||||
int n_used_mmu_pages = kvm->arch.n_alloc_mmu_pages
|
||||
- kvm->arch.n_free_mmu_pages;
|
||||
|
||||
while (n_used_mmu_pages > kvm_nr_mmu_pages) {
|
||||
if (used_pages > kvm_nr_mmu_pages) {
|
||||
while (used_pages > kvm_nr_mmu_pages) {
|
||||
struct kvm_mmu_page *page;
|
||||
|
||||
page = container_of(kvm->arch.active_mmu_pages.prev,
|
||||
struct kvm_mmu_page, link);
|
||||
kvm_mmu_zap_page(kvm, page);
|
||||
n_used_mmu_pages--;
|
||||
used_pages--;
|
||||
}
|
||||
kvm->arch.n_free_mmu_pages = 0;
|
||||
}
|
||||
@@ -1740,6 +1761,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
|
||||
{
|
||||
int was_rmapped = 0;
|
||||
int was_writeble = is_writeble_pte(*shadow_pte);
|
||||
int rmap_count;
|
||||
|
||||
pgprintk("%s: spte %llx access %x write_fault %d"
|
||||
" user_fault %d gfn %lx\n",
|
||||
@@ -1781,9 +1803,11 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
|
||||
|
||||
page_header_update_slot(vcpu->kvm, shadow_pte, gfn);
|
||||
if (!was_rmapped) {
|
||||
rmap_add(vcpu, shadow_pte, gfn, largepage);
|
||||
rmap_count = rmap_add(vcpu, shadow_pte, gfn, largepage);
|
||||
if (!is_rmap_pte(*shadow_pte))
|
||||
kvm_release_pfn_clean(pfn);
|
||||
if (rmap_count > RMAP_RECYCLE_THRESHOLD)
|
||||
rmap_recycle(vcpu, gfn, largepage);
|
||||
} else {
|
||||
if (was_writeble)
|
||||
kvm_release_pfn_dirty(pfn);
|
||||
|
@@ -711,6 +711,7 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
||||
svm->vmcb->control.tsc_offset += delta;
|
||||
vcpu->cpu = cpu;
|
||||
kvm_migrate_timers(vcpu);
|
||||
svm->asid_generation = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
|
||||
@@ -1031,7 +1032,6 @@ static void new_asid(struct vcpu_svm *svm, struct svm_cpu_data *svm_data)
|
||||
svm->vmcb->control.tlb_ctl = TLB_CONTROL_FLUSH_ALL_ASID;
|
||||
}
|
||||
|
||||
svm->vcpu.cpu = svm_data->cpu;
|
||||
svm->asid_generation = svm_data->asid_generation;
|
||||
svm->vmcb->control.asid = svm_data->next_asid++;
|
||||
}
|
||||
@@ -2300,8 +2300,8 @@ static void pre_svm_run(struct vcpu_svm *svm)
|
||||
struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu);
|
||||
|
||||
svm->vmcb->control.tlb_ctl = TLB_CONTROL_DO_NOTHING;
|
||||
if (svm->vcpu.cpu != cpu ||
|
||||
svm->asid_generation != svm_data->asid_generation)
|
||||
/* FIXME: handle wraparound of asid_generation */
|
||||
if (svm->asid_generation != svm_data->asid_generation)
|
||||
new_asid(svm, svm_data);
|
||||
}
|
||||
|
||||
|
@@ -3157,8 +3157,8 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
|
||||
struct vcpu_vmx *vmx = to_vmx(vcpu);
|
||||
enum emulation_result err = EMULATE_DONE;
|
||||
|
||||
preempt_enable();
|
||||
local_irq_enable();
|
||||
preempt_enable();
|
||||
|
||||
while (!guest_state_valid(vcpu)) {
|
||||
err = emulate_instruction(vcpu, kvm_run, 0, 0, 0);
|
||||
@@ -3168,7 +3168,7 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
|
||||
|
||||
if (err != EMULATE_DONE) {
|
||||
kvm_report_emulation_failure(vcpu, "emulation failure");
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (signal_pending(current))
|
||||
@@ -3177,8 +3177,8 @@ static void handle_invalid_guest_state(struct kvm_vcpu *vcpu,
|
||||
schedule();
|
||||
}
|
||||
|
||||
local_irq_disable();
|
||||
preempt_disable();
|
||||
local_irq_disable();
|
||||
|
||||
vmx->invalid_state_emulation_result = err;
|
||||
}
|
||||
|
@@ -704,11 +704,48 @@ static bool msr_mtrr_valid(unsigned msr)
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool valid_pat_type(unsigned t)
|
||||
{
|
||||
return t < 8 && (1 << t) & 0xf3; /* 0, 1, 4, 5, 6, 7 */
|
||||
}
|
||||
|
||||
static bool valid_mtrr_type(unsigned t)
|
||||
{
|
||||
return t < 8 && (1 << t) & 0x73; /* 0, 1, 4, 5, 6 */
|
||||
}
|
||||
|
||||
static bool mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!msr_mtrr_valid(msr))
|
||||
return false;
|
||||
|
||||
if (msr == MSR_IA32_CR_PAT) {
|
||||
for (i = 0; i < 8; i++)
|
||||
if (!valid_pat_type((data >> (i * 8)) & 0xff))
|
||||
return false;
|
||||
return true;
|
||||
} else if (msr == MSR_MTRRdefType) {
|
||||
if (data & ~0xcff)
|
||||
return false;
|
||||
return valid_mtrr_type(data & 0xff);
|
||||
} else if (msr >= MSR_MTRRfix64K_00000 && msr <= MSR_MTRRfix4K_F8000) {
|
||||
for (i = 0; i < 8 ; i++)
|
||||
if (!valid_mtrr_type((data >> (i * 8)) & 0xff))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* variable MTRRs */
|
||||
return valid_mtrr_type(data & 0xff);
|
||||
}
|
||||
|
||||
static int set_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
|
||||
{
|
||||
u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
|
||||
|
||||
if (!msr_mtrr_valid(msr))
|
||||
if (!mtrr_valid(vcpu, msr, data))
|
||||
return 1;
|
||||
|
||||
if (msr == MSR_MTRRdefType) {
|
||||
@@ -1079,14 +1116,13 @@ long kvm_arch_dev_ioctl(struct file *filp,
|
||||
if (copy_to_user(user_msr_list, &msr_list, sizeof msr_list))
|
||||
goto out;
|
||||
r = -E2BIG;
|
||||
if (n < num_msrs_to_save)
|
||||
if (n < msr_list.nmsrs)
|
||||
goto out;
|
||||
r = -EFAULT;
|
||||
if (copy_to_user(user_msr_list->indices, &msrs_to_save,
|
||||
num_msrs_to_save * sizeof(u32)))
|
||||
goto out;
|
||||
if (copy_to_user(user_msr_list->indices
|
||||
+ num_msrs_to_save * sizeof(u32),
|
||||
if (copy_to_user(user_msr_list->indices + num_msrs_to_save,
|
||||
&emulated_msrs,
|
||||
ARRAY_SIZE(emulated_msrs) * sizeof(u32)))
|
||||
goto out;
|
||||
|
Reference in New Issue
Block a user