Skip to content

Commit

Permalink
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/l…
Browse files Browse the repository at this point in the history
…inux/kernel/git/tip/tip

Pull x86 fixes from Thomas Gleixner:
 "A set of x86 fixes and functional updates:

   - Prevent stale huge I/O TLB mappings on 32bit. A long standing bug
     which got exposed by KPTI support for 32bit

   - Prevent bogus access_ok() warnings in arch_stack_walk_user()

   - Add display quirks for Lenovo devices which have height and width
     swapped

   - Add the missing CR2 fixup for 32 bit async pagefaults. Fallout of
     the CR2 bug fix series.

   - Unbreak handling of force enabled HPET by moving the 'is HPET
     counting' check back to the original place.

   - A more accurate check for running on a hypervisor platform in the
     MDS mitigation code. Not perfect, but more accurate than the
     previous one.

   - Update a stale and confusing comment vs. IRQ stacks"

* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/speculation/mds: Apply more accurate check on hypervisor platform
  x86/hpet: Undo the early counter is counting check
  x86/entry/32: Pass cr2 to do_async_page_fault()
  x86/irq/64: Update stale comment
  x86/sysfb_efi: Add quirks for some devices with swapped width and height
  x86/stacktrace: Prevent access_ok() warnings in arch_stack_walk_user()
  mm/vmalloc: Sync unmappings in __purge_vmap_area_lazy()
  x86/mm: Sync also unmappings in vmalloc_sync_all()
  x86/mm: Check for pfn instead of page in vmalloc_sync_one()
  • Loading branch information
torvalds committed Jul 28, 2019
2 parents e24ce84 + 517c3ba commit a9815a4
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 23 deletions.
13 changes: 9 additions & 4 deletions arch/x86/entry/entry_32.S
Original file line number Diff line number Diff line change
Expand Up @@ -1443,15 +1443,20 @@ BUILD_INTERRUPT3(hv_stimer0_callback_vector, HYPERV_STIMER0_VECTOR,

ENTRY(page_fault)
ASM_CLAC
pushl $0; /* %gs's slot on the stack */
pushl $do_page_fault
jmp common_exception_read_cr2
END(page_fault)

common_exception_read_cr2:
/* the function address is in %gs's slot on the stack */
SAVE_ALL switch_stacks=1 skip_gs=1

ENCODE_FRAME_POINTER
UNWIND_ESPFIX_STACK

/* fixup %gs */
GS_TO_REG %ecx
movl PT_GS(%esp), %edi
REG_TO_PTGS %ecx
SET_KERNEL_GS %ecx

Expand All @@ -1463,9 +1468,9 @@ ENTRY(page_fault)

TRACE_IRQS_OFF
movl %esp, %eax # pt_regs pointer
call do_page_fault
CALL_NOSPEC %edi
jmp ret_from_exception
END(page_fault)
END(common_exception_read_cr2)

common_exception:
/* the function address is in %gs's slot on the stack */
Expand Down Expand Up @@ -1595,7 +1600,7 @@ END(general_protection)
ENTRY(async_page_fault)
ASM_CLAC
pushl $do_async_page_fault
jmp common_exception
jmp common_exception_read_cr2
END(async_page_fault)
#endif

Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/cpu/bugs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1226,7 +1226,7 @@ static ssize_t l1tf_show_state(char *buf)

static ssize_t mds_show_state(char *buf)
{
if (!hypervisor_is_type(X86_HYPER_NATIVE)) {
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
return sprintf(buf, "%s; SMT Host state unknown\n",
mds_strings[mds_mitigation]);
}
Expand Down
8 changes: 4 additions & 4 deletions arch/x86/kernel/head_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -193,10 +193,10 @@ ENTRY(secondary_startup_64)

/* Set up %gs.
*
* The base of %gs always points to the bottom of the irqstack
* union. If the stack protector canary is enabled, it is
* located at %gs:40. Note that, on SMP, the boot cpu uses
* init data section till per cpu areas are set up.
* The base of %gs always points to fixed_percpu_data. If the
* stack protector canary is enabled, it is located at %gs:40.
* Note that, on SMP, the boot cpu uses init data section until
* the per cpu areas are set up.
*/
movl $MSR_GS_BASE,%ecx
movl initial_gs(%rip),%eax
Expand Down
12 changes: 8 additions & 4 deletions arch/x86/kernel/hpet.c
Original file line number Diff line number Diff line change
Expand Up @@ -827,10 +827,6 @@ int __init hpet_enable(void)
if (!hpet_cfg_working())
goto out_nohpet;

/* Validate that the counter is counting */
if (!hpet_counting())
goto out_nohpet;

/*
* Read the period and check for a sane value:
*/
Expand Down Expand Up @@ -896,6 +892,14 @@ int __init hpet_enable(void)
}
hpet_print_config();

/*
* Validate that the counter is counting. This needs to be done
* after sanitizing the config registers to properly deal with
* force enabled HPETs.
*/
if (!hpet_counting())
goto out_nohpet;

clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);

if (id & HPET_ID_LEGSUP) {
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ copy_stack_frame(const void __user *fp, struct stack_frame_user *frame)
{
int ret;

if (!access_ok(fp, sizeof(*frame)))
if (__range_not_ok(fp, sizeof(*frame), TASK_SIZE))
return 0;

ret = 1;
Expand Down
46 changes: 46 additions & 0 deletions arch/x86/kernel/sysfb_efi.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,55 @@ static const struct dmi_system_id efifb_dmi_system_table[] __initconst = {
{},
};

/*
* Some devices have a portrait LCD but advertise a landscape resolution (and
* pitch). We simply swap width and height for these devices so that we can
* correctly deal with some of them coming with multiple resolutions.
*/
static const struct dmi_system_id efifb_dmi_swap_width_height[] __initconst = {
{
/*
* Lenovo MIIX310-10ICR, only some batches have the troublesome
* 800x1280 portrait screen. Luckily the portrait version has
* its own BIOS version, so we match on that.
*/
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "MIIX 310-10ICR"),
DMI_EXACT_MATCH(DMI_BIOS_VERSION, "1HCN44WW"),
},
},
{
/* Lenovo MIIX 320-10ICR with 800x1280 portrait screen */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
"Lenovo MIIX 320-10ICR"),
},
},
{
/* Lenovo D330 with 800x1280 or 1200x1920 portrait screen */
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
DMI_EXACT_MATCH(DMI_PRODUCT_VERSION,
"Lenovo ideapad D330-10IGM"),
},
},
{},
};

__init void sysfb_apply_efi_quirks(void)
{
if (screen_info.orig_video_isVGA != VIDEO_TYPE_EFI ||
!(screen_info.capabilities & VIDEO_CAPABILITY_SKIP_QUIRKS))
dmi_check_system(efifb_dmi_system_table);

if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI &&
dmi_check_system(efifb_dmi_swap_width_height)) {
u16 temp = screen_info.lfb_width;

screen_info.lfb_width = screen_info.lfb_height;
screen_info.lfb_height = temp;
screen_info.lfb_linelength = 4 * screen_info.lfb_width;
}
}
15 changes: 6 additions & 9 deletions arch/x86/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,13 +177,14 @@ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)

pmd = pmd_offset(pud, address);
pmd_k = pmd_offset(pud_k, address);
if (!pmd_present(*pmd_k))
return NULL;

if (!pmd_present(*pmd))
if (pmd_present(*pmd) != pmd_present(*pmd_k))
set_pmd(pmd, *pmd_k);

if (!pmd_present(*pmd_k))
return NULL;
else
BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
BUG_ON(pmd_pfn(*pmd) != pmd_pfn(*pmd_k));

return pmd_k;
}
Expand All @@ -203,17 +204,13 @@ void vmalloc_sync_all(void)
spin_lock(&pgd_lock);
list_for_each_entry(page, &pgd_list, lru) {
spinlock_t *pgt_lock;
pmd_t *ret;

/* the pgt_lock only for Xen */
pgt_lock = &pgd_page_get_mm(page)->page_table_lock;

spin_lock(pgt_lock);
ret = vmalloc_sync_one(page_address(page), address);
vmalloc_sync_one(page_address(page), address);
spin_unlock(pgt_lock);

if (!ret)
break;
}
spin_unlock(&pgd_lock);
}
Expand Down
9 changes: 9 additions & 0 deletions mm/vmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1258,6 +1258,12 @@ static bool __purge_vmap_area_lazy(unsigned long start, unsigned long end)
if (unlikely(valist == NULL))
return false;

/*
* First make sure the mappings are removed from all page-tables
* before they are freed.
*/
vmalloc_sync_all();

/*
* TODO: to calculate a flush range without looping.
* The list can be up to lazy_max_pages() elements.
Expand Down Expand Up @@ -3038,6 +3044,9 @@ EXPORT_SYMBOL(remap_vmalloc_range);
/*
* Implement a stub for vmalloc_sync_all() if the architecture chose not to
* have one.
*
* The purpose of this function is to make sure the vmalloc area
* mappings are identical in all page-tables in the system.
*/
void __weak vmalloc_sync_all(void)
{
Expand Down

0 comments on commit a9815a4

Please sign in to comment.