.. | .. |
---|
363 | 363 | |
---|
364 | 364 | static inline bool kvm_is_write_fault(struct kvm_vcpu *vcpu) |
---|
365 | 365 | { |
---|
366 | | - if (kvm_vcpu_abt_iss1tw(vcpu)) |
---|
367 | | - return true; |
---|
| 366 | + if (kvm_vcpu_abt_iss1tw(vcpu)) { |
---|
| 367 | + /* |
---|
| 368 | + * Only a permission fault on a S1PTW should be |
---|
| 369 | + * considered as a write. Otherwise, page tables baked |
---|
| 370 | + * in a read-only memslot will result in an exception |
---|
| 371 | + * being delivered in the guest. |
---|
| 372 | + * |
---|
| 373 | + * The drawback is that we end-up faulting twice if the |
---|
| 374 | + * guest is using any of HW AF/DB: a translation fault |
---|
| 375 | + * to map the page containing the PT (read only at |
---|
| 376 | + * first), then a permission fault to allow the flags |
---|
| 377 | + * to be set. |
---|
| 378 | + */ |
---|
| 379 | + switch (kvm_vcpu_trap_get_fault_type(vcpu)) { |
---|
| 380 | + case ESR_ELx_FSC_PERM: |
---|
| 381 | + return true; |
---|
| 382 | + default: |
---|
| 383 | + return false; |
---|
| 384 | + } |
---|
| 385 | + } |
---|
368 | 386 | |
---|
369 | 387 | if (kvm_vcpu_trap_is_iabt(vcpu)) |
---|
370 | 388 | return false; |
---|