| .. | .. |
|---|
| 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; |
|---|