>>> On 06.09.12 at 15:15, Matt Fleming <matt@xxxxxxxxxxxxxxxxx> wrote: > From: Matt Fleming <matt.fleming@xxxxxxxxx> > > Some firmware still needs a 1:1 (virt->phys) mapping even after we've > called SetVirtualAddressMap(). So install the mapping alongside our > existing kernel mapping whenever we make EFI calls in virtual mode. > > This bug was discovered on ASUS machines where the firmware > implementation of GetTime() accesses the RTC device via physical > addresses, even though that's bogus per the UEFI spec since we've > informed the firmware via SetVirtualAddressMap() that the boottime > memory map is no longer valid. > @@ -741,6 +742,114 @@ static void __init runtime_code_page_mkexec(void) > } > } > > +#ifdef CONFIG_X86_64 > +pgd_t *efi_one_to_one_pgd; > +int efi_one_to_one_index = 0; I wasn't able to spot where this variable ever gets set to a non-zero value. > @@ -58,6 +62,47 @@ static void __init early_code_mapping_set_exec(int > executable) > } > } > > +pgd_t *efi_call_virt_prelog(void) > +{ > + pgd_t *save; > + int i; > + > + save = kmalloc(sizeof(pgd_t) * (efi_one_to_one_index + 1), GFP_KERNEL); GFP_ATOMIC perhaps, given that many runtime calls happen inside spin locks? > + if (!save) { > + pr_alert("Unable to save pgd entries\n"); > + return NULL; > + } > + > + for (i = 0; i <= efi_one_to_one_index; i++) { > + pgd_t *pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK); I'd suggest moving this out of the loop (also below), slightly adjusting the rest of the loop body. > + > + pgd += i; > + save[i] = *pgd; > + set_pgd(pgd, efi_one_to_one_pgd[i]); > + } Did you, as an alternative, consider switching to a different CR3 instead of copying back and forth? > + > + __flush_tlb_all(); Is it certain you will _never_ hit a global mapping (in which case I believe the above would be insufficient)? Jan > + return save; > +} > + > +void efi_call_virt_epilog(pgd_t *save) > +{ > + int i; > + > + if (!save) > + return; > + > + for (i = 0; i <= efi_one_to_one_index; i++) { > + pgd_t *pgd = __va(read_cr3() & PHYSICAL_PAGE_MASK); > + > + pgd += i; > + set_pgd(pgd, save[i]); > + } > + > + kfree(save); > + __flush_tlb_all(); > +} > + > void __init efi_call_phys_prelog(void) > { > unsigned long vaddress; > -- > 1.7.4.4 -- To unsubscribe from this list: send the line "unsubscribe linux-efi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html