/* * Structure for a nested guest, that is, for a guest that is managed by * one of our guests.
*/ struct kvm_nested_guest { struct kvm *l1_host; /* L1 VM that owns this nested guest */ int l1_lpid; /* lpid L1 guest thinks this guest is */ int shadow_lpid; /* real lpid of this nested guest */
pgd_t *shadow_pgtable; /* our page table for this guest */
u64 l1_gr_to_hr; /* L1's addr of part'n-scoped table */
u64 process_table; /* process table entry for this guest */ long refcnt; /* number of pointers to this struct */ struct mutex tlb_lock; /* serialize page faults and tlbies */ struct kvm_nested_guest *next;
cpumask_t need_tlb_flush; short prev_cpu[NR_CPUS];
u8 radix; /* is this nested guest radix */
};
/* * We define a nested rmap entry as a single 64-bit quantity * 0xFFF0000000000000 12-bit lpid field * 0x000FFFFFFFFFF000 40-bit guest 4k page frame number * 0x0000000000000001 1-bit single entry flag
*/ #define RMAP_NESTED_LPID_MASK 0xFFF0000000000000UL #define RMAP_NESTED_LPID_SHIFT (52) #define RMAP_NESTED_GPA_MASK 0x000FFFFFFFFFF000UL #define RMAP_NESTED_IS_SINGLE_ENTRY 0x0000000000000001UL
/* Structure for a nested guest rmap entry */ struct rmap_nested { struct llist_node list;
u64 rmap;
};
/* * for_each_nest_rmap_safe - iterate over the list of nested rmap entries * safe against removal of the list entry or NULL list * @pos: a (struct rmap_nested *) to use as a loop cursor * @node: pointer to the first entry * NOTE: this can be NULL * @rmapp: an (unsigned long *) in which to return the rmap entries on each * iteration * NOTE: this must point to already allocated memory * * The nested_rmap is a llist of (struct rmap_nested) entries pointed to by the * rmap entry in the memslot. The list is always terminated by a "single entry" * stored in the list element of the final entry of the llist. If there is ONLY * a single entry then this is itself in the rmap entry of the memslot, not a * llist head pointer. * * Note that the iterator below assumes that a nested rmap entry is always * non-zero. This is true for our usage because the LPID field is always * non-zero (zero is reserved for the host). * * This should be used to iterate over the list of rmap_nested entries with * processing done on the u64 rmap value given by each iteration. This is safe * against removal of list entries and it is always safe to call free on (pos). * * e.g. * struct rmap_nested *cursor; * struct llist_node *first; * unsigned long rmap; * for_each_nest_rmap_safe(cursor, first, &rmap) { * do_something(rmap); * free(cursor); * }
*/ #define for_each_nest_rmap_safe(pos, node, rmapp) \ for ((pos) = llist_entry((node), typeof(*(pos)), list); \
(node) && \
(*(rmapp) = ((RMAP_NESTED_IS_SINGLE_ENTRY & ((u64) (node))) ? \
((u64) (node)) : ((pos)->rmap))) && \
(((node) = ((RMAP_NESTED_IS_SINGLE_ENTRY & ((u64) (node))) ? \
((struct llist_node *) ((pos) = NULL)) : \
(pos)->list.next)), true); \
(pos) = llist_entry((node), typeof(*(pos)), list))
struct kvm_nested_guest *kvmhv_get_nested(struct kvm *kvm, int l1_lpid, bool create); void kvmhv_put_nested(struct kvm_nested_guest *gp); int kvmhv_nested_next_lpid(struct kvm *kvm, int lpid);
/* Encoding of first parameter for H_TLB_INVALIDATE */ #define H_TLBIE_P1_ENC(ric, prs, r) (___PPC_RIC(ric) | ___PPC_PRS(prs) | \
___PPC_R(r))
/* Power architecture requires HPT is at least 256kiB, at most 64TiB */ #define PPC_MIN_HPT_ORDER 18 #define PPC_MAX_HPT_ORDER 46
int kvmhv_vcpu_entry_p9(struct kvm_vcpu *vcpu, u64 time_limit, unsignedlong lpcr, u64 *tb);
#define KVM_DEFAULT_HPT_ORDER 24 /* 16MB HPT by default */ #endif
/* * Invalid HDSISR value which is used to indicate when HW has not set the reg. * Used to work around an errata.
*/ #define HDSISR_CANARY 0x7fff
/* * We use a lock bit in HPTE dword 0 to synchronize updates and * accesses to each HPTE, and another bit to indicate non-present * HPTEs.
*/ #define HPTE_V_HVLOCK 0x40UL #define HPTE_V_ABSENT 0x20UL
/* * We use this bit in the guest_rpte field of the revmap entry * to indicate a modified HPTE.
*/ #define HPTE_GR_MODIFIED (1ul << 62)
/* These bits are reserved in the guest view of the HPTE */ #define HPTE_GR_RESERVED HPTE_GR_MODIFIED
/* * We load/store in native endian, but the HTAB is in big endian. If * we byte swap all data we apply on the PTE we're implicitly correct * again.
*/
be_lockbit = cpu_to_be64(HPTE_V_HVLOCK);
be_bits = cpu_to_be64(bits);
/* * Ignore the top 14 bits of va * v have top two bits covering segment size, hence move * by 16 bits, Also clear the lower HPTE_V_AVPN_SHIFT (7) bits. * AVA field in v also have the lower 23 bits ignored. * For base page size 4K we need 14 .. 65 bits (so need to * collect extra 11 bits) * For others we need 14..14+i
*/ /* This covers 14..54 bits of va*/
rb = (v & ~0x7fUL) << 16; /* AVA field */
/* * AVA in v had cleared lower 23 bits. We need to derive * that from pteg index
*/
va_low = pte_index >> 3; if (v & HPTE_V_SECONDARY)
va_low = ~va_low; /* * get the vpn bits from va_low using reverse of hashing. * In v we have va with 23 bits dropped and then left shifted * HPTE_V_AVPN_SHIFT (7) bits. Now to find vsid we need * right shift it with (SID_SHIFT - (23 - 7))
*/ if (!(v & HPTE_V_1TB_SEG))
va_low ^= v >> (SID_SHIFT - 16); else
va_low ^= v >> (SID_SHIFT_1T - 16);
va_low &= 0x7ff;
if (b_pgshift <= 12) { if (a_pgshift > 12) {
sllp = (a_pgshift == 16) ? 5 : 4;
rb |= sllp << 5; /* AP field */
}
rb |= (va_low & 0x7ff) << 12; /* remaining 11 bits of AVA */
} else { int aval_shift; /* * remaining bits of AVA/LP fields * Also contain the rr bits of LP
*/
rb |= (va_low << b_pgshift) & 0x7ff000; /* * Now clear not needed LP bits based on actual psize
*/
rb &= ~((1ul << a_pgshift) - 1); /* * AVAL field 58..77 - base_page_shift bits of va * we have space for 58..64 bits, Missing bits should * be zero filled. +1 is to take care of L bit shift
*/
aval_shift = 64 - (77 - b_pgshift) + 1;
rb |= ((va_low << aval_shift) & 0xfe);
rb |= 1; /* L field */
rb |= r & 0xff000 & ((1ul << a_pgshift) - 1); /* LP field */
} /* * This sets both bits of the B field in the PTE. 0b1x values are * reserved, but those will have been filtered by kvmppc_do_h_enter.
*/
rb |= (v >> HPTE_V_SSIZE_SHIFT) << 8; /* B field */ return rb;
}
if (!is_ci) return wimg == HPTE_R_M; /* * if host is mapped cache inhibited, make sure hptel also have * cache inhibited.
*/ if (wimg & HPTE_R_W) /* FIXME!! is this ok for all guest. ? */ returnfalse; return !!(wimg & HPTE_R_I);
}
/* * If it's present and writable, atomically set dirty and referenced bits and * return the PTE, otherwise return 0.
*/ staticinline pte_t kvmppc_read_update_linux_pte(pte_t *ptep, int writing)
{
pte_t old_pte, new_pte = __pte(0);
while (1) { /* * Make sure we don't reload from ptep
*/
old_pte = READ_ONCE(*ptep); /* * wait until H_PAGE_BUSY is clear then set it atomically
*/ if (unlikely(pte_val(old_pte) & H_PAGE_BUSY)) {
cpu_relax(); continue;
} /* If pte is not present return None */ if (unlikely(!pte_present(old_pte))) return __pte(0);
new_pte = pte_mkyoung(old_pte); if (writing && pte_write(old_pte))
new_pte = pte_mkdirty(new_pte);
if (pte_xchg(ptep, old_pte, new_pte)) break;
} return new_pte;
}
staticinlinevoid lock_rmap(unsignedlong *rmap)
{ do { while (test_bit(KVMPPC_RMAP_LOCK_BIT, rmap))
cpu_relax();
} while (test_and_set_bit_lock(KVMPPC_RMAP_LOCK_BIT, rmap));
}
/* * This works for 4k, 64k and 16M pages on POWER7, * and 4k and 16M pages on PPC970.
*/ staticinlineunsignedlong slb_pgsize_encoding(unsignedlong psize)
{ unsignedlong senc = 0;
if (psize > 0x1000) {
senc = SLB_VSID_L; if (psize == 0x10000)
senc |= SLB_VSID_LP_01;
} return senc;
}
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE /* * Note modification of an HPTE; set the HPTE modified bit * if anyone is interested.
*/ staticinlinevoid note_hpte_modification(struct kvm *kvm, struct revmap_entry *rev)
{ if (atomic_read(&kvm->arch.hpte_mod_interest))
rev->guest_rpte |= HPTE_GR_MODIFIED;
}
/* * Like kvm_memslots(), but for use in real mode when we can't do * any RCU stuff (since the secondary threads are offline from the * kernel's point of view), and we can't print anything. * Thus we use rcu_dereference_raw() rather than rcu_dereference_check().
*/ staticinlinestruct kvm_memslots *kvm_memslots_raw(struct kvm *kvm)
{ return rcu_dereference_raw_check(kvm->memslots[0]);
}
VM_WARN(!spin_is_locked(&kvm->mmu_lock), "%s called with kvm mmu_lock not held \n", __func__);
pte = __find_linux_pte(kvm->arch.pgtable, ea, NULL, hshift);
¤ 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.0.28Bemerkung:
(vorverarbeitet)
¤
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.