Skip to content

Commit

Permalink
KVM: Remove memory alias support
Browse files Browse the repository at this point in the history
As advertised in feature-removal-schedule.txt.  Equivalent support is provided
by overlapping memory regions.

Signed-off-by: Avi Kivity <[email protected]>
  • Loading branch information
avikivity committed Aug 1, 2010
1 parent fc34531 commit a1f4d39
Show file tree
Hide file tree
Showing 13 changed files with 11 additions and 225 deletions.
11 changes: 0 additions & 11 deletions Documentation/feature-removal-schedule.txt
Original file line number Diff line number Diff line change
Expand Up @@ -538,17 +538,6 @@ Who: Jan Kiszka <[email protected]>

----------------------------

What: KVM memory aliases support
When: July 2010
Why: Memory aliasing support is used for speeding up guest vga access
through the vga windows.

Modern userspace no longer uses this feature, so it's just bitrotted
code and can be removed with no impact.
Who: Avi Kivity <[email protected]>

----------------------------

What: xtime, wall_to_monotonic
When: 2.6.36+
Files: kernel/time/timekeeping.c include/linux/time.h
Expand Down
12 changes: 1 addition & 11 deletions Documentation/kvm/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -226,17 +226,7 @@ Type: vm ioctl
Parameters: struct kvm_memory_alias (in)
Returns: 0 (success), -1 (error)

struct kvm_memory_alias {
__u32 slot; /* this has a different namespace than memory slots */
__u32 flags;
__u64 guest_phys_addr;
__u64 memory_size;
__u64 target_phys_addr;
};

Defines a guest physical address space region as an alias to another
region. Useful for aliased address, for example the VGA low memory
window. Should not be used with userspace memory.
This ioctl is obsolete and has been removed.

4.9 KVM_RUN

Expand Down
5 changes: 0 additions & 5 deletions arch/ia64/kvm/kvm-ia64.c
Original file line number Diff line number Diff line change
Expand Up @@ -1946,11 +1946,6 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
return vcpu->arch.timer_fired;
}

gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
{
return gfn;
}

int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
{
return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE) ||
Expand Down
5 changes: 0 additions & 5 deletions arch/powerpc/kvm/powerpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@
#define CREATE_TRACE_POINTS
#include "trace.h"

gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
{
return gfn;
}

int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
{
return !(v->arch.msr & MSR_WE) || !!(v->arch.pending_exceptions);
Expand Down
5 changes: 0 additions & 5 deletions arch/s390/kvm/kvm-s390.c
Original file line number Diff line number Diff line change
Expand Up @@ -723,11 +723,6 @@ void kvm_arch_flush_shadow(struct kvm *kvm)
{
}

gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
{
return gfn;
}

static int __init kvm_s390_init(void)
{
int ret;
Expand Down
21 changes: 0 additions & 21 deletions arch/x86/include/asm/kvm_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@

#define IOPL_SHIFT 12

#define KVM_ALIAS_SLOTS 4

#define KVM_PERMILLE_MMU_PAGES 20
#define KVM_MIN_ALLOC_MMU_PAGES 64
#define KVM_MMU_HASH_SHIFT 10
Expand Down Expand Up @@ -362,24 +360,7 @@ struct kvm_vcpu_arch {
u64 hv_vapic;
};

struct kvm_mem_alias {
gfn_t base_gfn;
unsigned long npages;
gfn_t target_gfn;
#define KVM_ALIAS_INVALID 1UL
unsigned long flags;
};

#define KVM_ARCH_HAS_UNALIAS_INSTANTIATION

struct kvm_mem_aliases {
struct kvm_mem_alias aliases[KVM_ALIAS_SLOTS];
int naliases;
};

struct kvm_arch {
struct kvm_mem_aliases *aliases;

unsigned int n_free_mmu_pages;
unsigned int n_requested_mmu_pages;
unsigned int n_alloc_mmu_pages;
Expand Down Expand Up @@ -655,8 +636,6 @@ void kvm_disable_tdp(void);
int complete_pio(struct kvm_vcpu *vcpu);
bool kvm_check_iopl(struct kvm_vcpu *vcpu);

struct kvm_memory_slot *gfn_to_memslot_unaliased(struct kvm *kvm, gfn_t gfn);

static inline struct kvm_mmu_page *page_header(hpa_t shadow_page)
{
struct page *page = pfn_to_page(shadow_page >> PAGE_SHIFT);
Expand Down
17 changes: 4 additions & 13 deletions arch/x86/kvm/mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,9 +434,7 @@ static void account_shadowed(struct kvm *kvm, gfn_t gfn)
int *write_count;
int i;

gfn = unalias_gfn(kvm, gfn);

slot = gfn_to_memslot_unaliased(kvm, gfn);
slot = gfn_to_memslot(kvm, gfn);
for (i = PT_DIRECTORY_LEVEL;
i < PT_PAGE_TABLE_LEVEL + KVM_NR_PAGE_SIZES; ++i) {
write_count = slot_largepage_idx(gfn, slot, i);
Expand All @@ -450,8 +448,7 @@ static void unaccount_shadowed(struct kvm *kvm, gfn_t gfn)
int *write_count;
int i;

gfn = unalias_gfn(kvm, gfn);
slot = gfn_to_memslot_unaliased(kvm, gfn);
slot = gfn_to_memslot(kvm, gfn);
for (i = PT_DIRECTORY_LEVEL;
i < PT_PAGE_TABLE_LEVEL + KVM_NR_PAGE_SIZES; ++i) {
write_count = slot_largepage_idx(gfn, slot, i);
Expand All @@ -467,8 +464,7 @@ static int has_wrprotected_page(struct kvm *kvm,
struct kvm_memory_slot *slot;
int *largepage_idx;

gfn = unalias_gfn(kvm, gfn);
slot = gfn_to_memslot_unaliased(kvm, gfn);
slot = gfn_to_memslot(kvm, gfn);
if (slot) {
largepage_idx = slot_largepage_idx(gfn, slot, level);
return *largepage_idx;
Expand Down Expand Up @@ -521,7 +517,6 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)

/*
* Take gfn and return the reverse mapping to it.
* Note: gfn must be unaliased before this function get called
*/

static unsigned long *gfn_to_rmap(struct kvm *kvm, gfn_t gfn, int level)
Expand Down Expand Up @@ -561,7 +556,6 @@ static int rmap_add(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)

if (!is_rmap_spte(*spte))
return count;
gfn = unalias_gfn(vcpu->kvm, gfn);
sp = page_header(__pa(spte));
kvm_mmu_page_set_gfn(sp, spte - sp->spt, gfn);
rmapp = gfn_to_rmap(vcpu->kvm, gfn, sp->role.level);
Expand Down Expand Up @@ -698,7 +692,6 @@ static int rmap_write_protect(struct kvm *kvm, u64 gfn)
u64 *spte;
int i, write_protected = 0;

gfn = unalias_gfn(kvm, gfn);
rmapp = gfn_to_rmap(kvm, gfn, PT_PAGE_TABLE_LEVEL);

spte = rmap_next(kvm, rmapp, NULL);
Expand Down Expand Up @@ -885,7 +878,6 @@ static void rmap_recycle(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn)

sp = page_header(__pa(spte));

gfn = unalias_gfn(vcpu->kvm, gfn);
rmapp = gfn_to_rmap(vcpu->kvm, gfn, sp->role.level);

kvm_unmap_rmapp(vcpu->kvm, rmapp, 0);
Expand Down Expand Up @@ -3510,8 +3502,7 @@ static void audit_write_protection(struct kvm_vcpu *vcpu)
if (sp->unsync)
continue;

gfn = unalias_gfn(vcpu->kvm, sp->gfn);
slot = gfn_to_memslot_unaliased(vcpu->kvm, sp->gfn);
slot = gfn_to_memslot(vcpu->kvm, sp->gfn);
rmapp = &slot->rmap[gfn - slot->base_gfn];

spte = rmap_next(vcpu->kvm, rmapp, NULL);
Expand Down
3 changes: 1 addition & 2 deletions arch/x86/kvm/paging_tmpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,6 @@ static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu,
* Using the cached information from sp->gfns is safe because:
* - The spte has a reference to the struct page, so the pfn for a given gfn
* can't change unless all sptes pointing to it are nuked first.
* - Alias changes zap the entire shadow cache.
*/
static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
bool clear_unsync)
Expand Down Expand Up @@ -611,7 +610,7 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
return -EINVAL;

gfn = gpte_to_gfn(gpte);
if (unalias_gfn(vcpu->kvm, gfn) != sp->gfns[i] ||
if (gfn != sp->gfns[i] ||
!is_present_gpte(gpte) || !(gpte & PT_ACCESSED_MASK)) {
u64 nonpresent;

Expand Down
125 changes: 0 additions & 125 deletions arch/x86/kvm/x86.c
Original file line number Diff line number Diff line change
Expand Up @@ -2740,115 +2740,6 @@ static int kvm_vm_ioctl_get_nr_mmu_pages(struct kvm *kvm)
return kvm->arch.n_alloc_mmu_pages;
}

gfn_t unalias_gfn_instantiation(struct kvm *kvm, gfn_t gfn)
{
int i;
struct kvm_mem_alias *alias;
struct kvm_mem_aliases *aliases;

aliases = kvm_aliases(kvm);

for (i = 0; i < aliases->naliases; ++i) {
alias = &aliases->aliases[i];
if (alias->flags & KVM_ALIAS_INVALID)
continue;
if (gfn >= alias->base_gfn
&& gfn < alias->base_gfn + alias->npages)
return alias->target_gfn + gfn - alias->base_gfn;
}
return gfn;
}

gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
{
int i;
struct kvm_mem_alias *alias;
struct kvm_mem_aliases *aliases;

aliases = kvm_aliases(kvm);

for (i = 0; i < aliases->naliases; ++i) {
alias = &aliases->aliases[i];
if (gfn >= alias->base_gfn
&& gfn < alias->base_gfn + alias->npages)
return alias->target_gfn + gfn - alias->base_gfn;
}
return gfn;
}

/*
* Set a new alias region. Aliases map a portion of physical memory into
* another portion. This is useful for memory windows, for example the PC
* VGA region.
*/
static int kvm_vm_ioctl_set_memory_alias(struct kvm *kvm,
struct kvm_memory_alias *alias)
{
int r, n;
struct kvm_mem_alias *p;
struct kvm_mem_aliases *aliases, *old_aliases;

r = -EINVAL;
/* General sanity checks */
if (alias->memory_size & (PAGE_SIZE - 1))
goto out;
if (alias->guest_phys_addr & (PAGE_SIZE - 1))
goto out;
if (alias->slot >= KVM_ALIAS_SLOTS)
goto out;
if (alias->guest_phys_addr + alias->memory_size
< alias->guest_phys_addr)
goto out;
if (alias->target_phys_addr + alias->memory_size
< alias->target_phys_addr)
goto out;

r = -ENOMEM;
aliases = kzalloc(sizeof(struct kvm_mem_aliases), GFP_KERNEL);
if (!aliases)
goto out;

mutex_lock(&kvm->slots_lock);

/* invalidate any gfn reference in case of deletion/shrinking */
memcpy(aliases, kvm->arch.aliases, sizeof(struct kvm_mem_aliases));
aliases->aliases[alias->slot].flags |= KVM_ALIAS_INVALID;
old_aliases = kvm->arch.aliases;
rcu_assign_pointer(kvm->arch.aliases, aliases);
synchronize_srcu_expedited(&kvm->srcu);
kvm_mmu_zap_all(kvm);
kfree(old_aliases);

r = -ENOMEM;
aliases = kzalloc(sizeof(struct kvm_mem_aliases), GFP_KERNEL);
if (!aliases)
goto out_unlock;

memcpy(aliases, kvm->arch.aliases, sizeof(struct kvm_mem_aliases));

p = &aliases->aliases[alias->slot];
p->base_gfn = alias->guest_phys_addr >> PAGE_SHIFT;
p->npages = alias->memory_size >> PAGE_SHIFT;
p->target_gfn = alias->target_phys_addr >> PAGE_SHIFT;
p->flags &= ~(KVM_ALIAS_INVALID);

for (n = KVM_ALIAS_SLOTS; n > 0; --n)
if (aliases->aliases[n - 1].npages)
break;
aliases->naliases = n;

old_aliases = kvm->arch.aliases;
rcu_assign_pointer(kvm->arch.aliases, aliases);
synchronize_srcu_expedited(&kvm->srcu);
kfree(old_aliases);
r = 0;

out_unlock:
mutex_unlock(&kvm->slots_lock);
out:
return r;
}

static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm, struct kvm_irqchip *chip)
{
int r;
Expand Down Expand Up @@ -3056,7 +2947,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
union {
struct kvm_pit_state ps;
struct kvm_pit_state2 ps2;
struct kvm_memory_alias alias;
struct kvm_pit_config pit_config;
} u;

Expand Down Expand Up @@ -3101,14 +2991,6 @@ long kvm_arch_vm_ioctl(struct file *filp,
case KVM_GET_NR_MMU_PAGES:
r = kvm_vm_ioctl_get_nr_mmu_pages(kvm);
break;
case KVM_SET_MEMORY_ALIAS:
r = -EFAULT;
if (copy_from_user(&u.alias, argp, sizeof(struct kvm_memory_alias)))
goto out;
r = kvm_vm_ioctl_set_memory_alias(kvm, &u.alias);
if (r)
goto out;
break;
case KVM_CREATE_IRQCHIP: {
struct kvm_pic *vpic;

Expand Down Expand Up @@ -5559,12 +5441,6 @@ struct kvm *kvm_arch_create_vm(void)
if (!kvm)
return ERR_PTR(-ENOMEM);

kvm->arch.aliases = kzalloc(sizeof(struct kvm_mem_aliases), GFP_KERNEL);
if (!kvm->arch.aliases) {
kfree(kvm);
return ERR_PTR(-ENOMEM);
}

INIT_LIST_HEAD(&kvm->arch.active_mmu_pages);
INIT_LIST_HEAD(&kvm->arch.assigned_dev_head);

Expand Down Expand Up @@ -5622,7 +5498,6 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
if (kvm->arch.ept_identity_pagetable)
put_page(kvm->arch.ept_identity_pagetable);
cleanup_srcu_struct(&kvm->srcu);
kfree(kvm->arch.aliases);
kfree(kvm);
}

Expand Down
7 changes: 0 additions & 7 deletions arch/x86/kvm/x86.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,6 @@ static inline int is_paging(struct kvm_vcpu *vcpu)
return kvm_read_cr0_bits(vcpu, X86_CR0_PG);
}

static inline struct kvm_mem_aliases *kvm_aliases(struct kvm *kvm)
{
return rcu_dereference_check(kvm->arch.aliases,
srcu_read_lock_held(&kvm->srcu)
|| lockdep_is_held(&kvm->slots_lock));
}

void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);

Expand Down
1 change: 1 addition & 0 deletions include/linux/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,7 @@ struct kvm_clock_data {
*/
#define KVM_CREATE_VCPU _IO(KVMIO, 0x41)
#define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log)
/* KVM_SET_MEMORY_ALIAS is obsolete: */
#define KVM_SET_MEMORY_ALIAS _IOW(KVMIO, 0x43, struct kvm_memory_alias)
#define KVM_SET_NR_MMU_PAGES _IO(KVMIO, 0x44)
#define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45)
Expand Down
Loading

0 comments on commit a1f4d39

Please sign in to comment.