Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: e500: track host-writability of pages

Add the possibility of marking a page so that the UW and SW bits are
force-cleared. This is stored in the private info so that it persists
across multiple calls to kvmppc_e500_setup_stlbe.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

+13 -4
+2
arch/powerpc/kvm/e500.h
··· 34 34 #define E500_TLB_BITMAP (1 << 30) 35 35 /* TLB1 entry is mapped by host TLB0 */ 36 36 #define E500_TLB_TLB0 (1 << 29) 37 + /* entry is writable on the host */ 38 + #define E500_TLB_WRITABLE (1 << 28) 37 39 /* bits [6-5] MAS2_X1 and MAS2_X0 and [4-0] bits for WIMGE */ 38 40 #define E500_TLB_MAS2_ATTR (0x7f) 39 41
+11 -4
arch/powerpc/kvm/e500_mmu_host.c
··· 45 45 return host_tlb_params[1].entries - tlbcam_index - 1; 46 46 } 47 47 48 - static inline u32 e500_shadow_mas3_attrib(u32 mas3, int usermode) 48 + static inline u32 e500_shadow_mas3_attrib(u32 mas3, bool writable, int usermode) 49 49 { 50 50 /* Mask off reserved bits. */ 51 51 mas3 &= MAS3_ATTRIB_MASK; 52 + 53 + if (!writable) 54 + mas3 &= ~(MAS3_UW|MAS3_SW); 52 55 53 56 #ifndef CONFIG_KVM_BOOKE_HV 54 57 if (!usermode) { ··· 247 244 248 245 static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref, 249 246 struct kvm_book3e_206_tlb_entry *gtlbe, 250 - kvm_pfn_t pfn, unsigned int wimg) 247 + kvm_pfn_t pfn, unsigned int wimg, 248 + bool writable) 251 249 { 252 250 ref->pfn = pfn; 253 251 ref->flags = E500_TLB_VALID; 252 + if (writable) 253 + ref->flags |= E500_TLB_WRITABLE; 254 254 255 255 /* Use guest supplied MAS2_G and MAS2_E */ 256 256 ref->flags |= (gtlbe->mas2 & MAS2_ATTRIB_MASK) | wimg; ··· 309 303 { 310 304 kvm_pfn_t pfn = ref->pfn; 311 305 u32 pr = vcpu->arch.shared->msr & MSR_PR; 306 + bool writable = !!(ref->flags & E500_TLB_WRITABLE); 312 307 313 308 BUG_ON(!(ref->flags & E500_TLB_VALID)); 314 309 ··· 317 310 stlbe->mas1 = MAS1_TSIZE(tsize) | get_tlb_sts(gtlbe) | MAS1_VALID; 318 311 stlbe->mas2 = (gvaddr & MAS2_EPN) | (ref->flags & E500_TLB_MAS2_ATTR); 319 312 stlbe->mas7_3 = ((u64)pfn << PAGE_SHIFT) | 320 - e500_shadow_mas3_attrib(gtlbe->mas7_3, pr); 313 + e500_shadow_mas3_attrib(gtlbe->mas7_3, writable, pr); 321 314 } 322 315 323 316 static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, ··· 494 487 } 495 488 local_irq_restore(flags); 496 489 497 - kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg); 490 + kvmppc_e500_ref_setup(ref, gtlbe, pfn, wimg, true); 498 491 kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize, 499 492 ref, gvaddr, stlbe); 500 493 writable = tlbe_is_writable(stlbe);