Merge commit 3669ef9fa7
("x86, tls: Interpret an all-zero struct user_desc as 'no segment'") into x86/asm
Pick up the latestest asm fixes before advancing it any further. Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
41ca5d4e9b
161 changed files with 1333 additions and 570 deletions
|
@ -611,20 +611,20 @@ void __init acpi_pic_sci_set_trigger(unsigned int irq, u16 trigger)
|
|||
|
||||
int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp)
|
||||
{
|
||||
int irq;
|
||||
int rc, irq, trigger, polarity;
|
||||
|
||||
if (acpi_irq_model == ACPI_IRQ_MODEL_PIC) {
|
||||
*irqp = gsi;
|
||||
} else {
|
||||
mutex_lock(&acpi_ioapic_lock);
|
||||
irq = mp_map_gsi_to_irq(gsi,
|
||||
IOAPIC_MAP_ALLOC | IOAPIC_MAP_CHECK);
|
||||
mutex_unlock(&acpi_ioapic_lock);
|
||||
if (irq < 0)
|
||||
return -1;
|
||||
*irqp = irq;
|
||||
rc = acpi_get_override_irq(gsi, &trigger, &polarity);
|
||||
if (rc == 0) {
|
||||
trigger = trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
|
||||
polarity = polarity ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
|
||||
irq = acpi_register_gsi(NULL, gsi, trigger, polarity);
|
||||
if (irq >= 0) {
|
||||
*irqp = irq;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
|
||||
|
||||
|
|
|
@ -107,6 +107,7 @@ static struct clocksource hyperv_cs = {
|
|||
.rating = 400, /* use this when running on Hyperv*/
|
||||
.read = read_hv_clock,
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
static void __init ms_hyperv_init_platform(void)
|
||||
|
|
|
@ -568,8 +568,8 @@ struct event_constraint intel_atom_pebs_event_constraints[] = {
|
|||
};
|
||||
|
||||
struct event_constraint intel_slm_pebs_event_constraints[] = {
|
||||
/* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */
|
||||
INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf),
|
||||
/* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */
|
||||
INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x1),
|
||||
/* Allow all events as PEBS with no flags */
|
||||
INTEL_ALL_EVENT_CONSTRAINT(0, 0x1),
|
||||
EVENT_CONSTRAINT_END
|
||||
|
|
|
@ -103,6 +103,13 @@ static struct kobj_attribute format_attr_##_var = \
|
|||
|
||||
#define RAPL_CNTR_WIDTH 32 /* 32-bit rapl counters */
|
||||
|
||||
#define RAPL_EVENT_ATTR_STR(_name, v, str) \
|
||||
static struct perf_pmu_events_attr event_attr_##v = { \
|
||||
.attr = __ATTR(_name, 0444, rapl_sysfs_show, NULL), \
|
||||
.id = 0, \
|
||||
.event_str = str, \
|
||||
};
|
||||
|
||||
struct rapl_pmu {
|
||||
spinlock_t lock;
|
||||
int hw_unit; /* 1/2^hw_unit Joule */
|
||||
|
@ -379,23 +386,36 @@ static struct attribute_group rapl_pmu_attr_group = {
|
|||
.attrs = rapl_pmu_attrs,
|
||||
};
|
||||
|
||||
EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01");
|
||||
EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02");
|
||||
EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03");
|
||||
EVENT_ATTR_STR(energy-gpu , rapl_gpu, "event=0x04");
|
||||
static ssize_t rapl_sysfs_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *page)
|
||||
{
|
||||
struct perf_pmu_events_attr *pmu_attr = \
|
||||
container_of(attr, struct perf_pmu_events_attr, attr);
|
||||
|
||||
EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules");
|
||||
EVENT_ATTR_STR(energy-pkg.unit , rapl_pkg_unit, "Joules");
|
||||
EVENT_ATTR_STR(energy-ram.unit , rapl_ram_unit, "Joules");
|
||||
EVENT_ATTR_STR(energy-gpu.unit , rapl_gpu_unit, "Joules");
|
||||
if (pmu_attr->event_str)
|
||||
return sprintf(page, "%s", pmu_attr->event_str);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
RAPL_EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01");
|
||||
RAPL_EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02");
|
||||
RAPL_EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03");
|
||||
RAPL_EVENT_ATTR_STR(energy-gpu , rapl_gpu, "event=0x04");
|
||||
|
||||
RAPL_EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules");
|
||||
RAPL_EVENT_ATTR_STR(energy-pkg.unit , rapl_pkg_unit, "Joules");
|
||||
RAPL_EVENT_ATTR_STR(energy-ram.unit , rapl_ram_unit, "Joules");
|
||||
RAPL_EVENT_ATTR_STR(energy-gpu.unit , rapl_gpu_unit, "Joules");
|
||||
|
||||
/*
|
||||
* we compute in 0.23 nJ increments regardless of MSR
|
||||
*/
|
||||
EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10");
|
||||
EVENT_ATTR_STR(energy-pkg.scale, rapl_pkg_scale, "2.3283064365386962890625e-10");
|
||||
EVENT_ATTR_STR(energy-ram.scale, rapl_ram_scale, "2.3283064365386962890625e-10");
|
||||
EVENT_ATTR_STR(energy-gpu.scale, rapl_gpu_scale, "2.3283064365386962890625e-10");
|
||||
RAPL_EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890625e-10");
|
||||
RAPL_EVENT_ATTR_STR(energy-pkg.scale, rapl_pkg_scale, "2.3283064365386962890625e-10");
|
||||
RAPL_EVENT_ATTR_STR(energy-ram.scale, rapl_ram_scale, "2.3283064365386962890625e-10");
|
||||
RAPL_EVENT_ATTR_STR(energy-gpu.scale, rapl_gpu_scale, "2.3283064365386962890625e-10");
|
||||
|
||||
static struct attribute *rapl_events_srv_attr[] = {
|
||||
EVENT_PTR(rapl_cores),
|
||||
|
|
|
@ -127,7 +127,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
|
|||
seq_puts(p, " Machine check polls\n");
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_HYPERV) || defined(CONFIG_XEN)
|
||||
seq_printf(p, "%*s: ", prec, "THR");
|
||||
seq_printf(p, "%*s: ", prec, "HYP");
|
||||
for_each_online_cpu(j)
|
||||
seq_printf(p, "%10u ", irq_stats(j)->irq_hv_callback_count);
|
||||
seq_puts(p, " Hypervisor callback interrupts\n");
|
||||
|
|
|
@ -1020,6 +1020,15 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
|
|||
regs->flags &= ~X86_EFLAGS_IF;
|
||||
trace_hardirqs_off();
|
||||
regs->ip = (unsigned long)(jp->entry);
|
||||
|
||||
/*
|
||||
* jprobes use jprobe_return() which skips the normal return
|
||||
* path of the function, and this messes up the accounting of the
|
||||
* function graph tracer to get messed up.
|
||||
*
|
||||
* Pause function graph tracing while performing the jprobe function.
|
||||
*/
|
||||
pause_graph_tracing();
|
||||
return 1;
|
||||
}
|
||||
NOKPROBE_SYMBOL(setjmp_pre_handler);
|
||||
|
@ -1048,24 +1057,25 @@ int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
|
|||
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
||||
u8 *addr = (u8 *) (regs->ip - 1);
|
||||
struct jprobe *jp = container_of(p, struct jprobe, kp);
|
||||
void *saved_sp = kcb->jprobe_saved_sp;
|
||||
|
||||
if ((addr > (u8 *) jprobe_return) &&
|
||||
(addr < (u8 *) jprobe_return_end)) {
|
||||
if (stack_addr(regs) != kcb->jprobe_saved_sp) {
|
||||
if (stack_addr(regs) != saved_sp) {
|
||||
struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
|
||||
printk(KERN_ERR
|
||||
"current sp %p does not match saved sp %p\n",
|
||||
stack_addr(regs), kcb->jprobe_saved_sp);
|
||||
stack_addr(regs), saved_sp);
|
||||
printk(KERN_ERR "Saved registers for jprobe %p\n", jp);
|
||||
show_regs(saved_regs);
|
||||
printk(KERN_ERR "Current registers\n");
|
||||
show_regs(regs);
|
||||
BUG();
|
||||
}
|
||||
/* It's OK to start function graph tracing again */
|
||||
unpause_graph_tracing();
|
||||
*regs = kcb->jprobe_saved_regs;
|
||||
memcpy((kprobe_opcode_t *)(kcb->jprobe_saved_sp),
|
||||
kcb->jprobes_stack,
|
||||
MIN_STACK_SIZE(kcb->jprobe_saved_sp));
|
||||
memcpy(saved_sp, kcb->jprobes_stack, MIN_STACK_SIZE(saved_sp));
|
||||
preempt_enable_no_resched();
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,28 @@ static int get_free_idx(void)
|
|||
|
||||
static bool tls_desc_okay(const struct user_desc *info)
|
||||
{
|
||||
if (LDT_empty(info))
|
||||
/*
|
||||
* For historical reasons (i.e. no one ever documented how any
|
||||
* of the segmentation APIs work), user programs can and do
|
||||
* assume that a struct user_desc that's all zeros except for
|
||||
* entry_number means "no segment at all". This never actually
|
||||
* worked. In fact, up to Linux 3.19, a struct user_desc like
|
||||
* this would create a 16-bit read-write segment with base and
|
||||
* limit both equal to zero.
|
||||
*
|
||||
* That was close enough to "no segment at all" until we
|
||||
* hardened this function to disallow 16-bit TLS segments. Fix
|
||||
* it up by interpreting these zeroed segments the way that they
|
||||
* were almost certainly intended to be interpreted.
|
||||
*
|
||||
* The correct way to ask for "no segment at all" is to specify
|
||||
* a user_desc that satisfies LDT_empty. To keep everything
|
||||
* working, we accept both.
|
||||
*
|
||||
* Note that there's a similar kludge in modify_ldt -- look at
|
||||
* the distinction between modes 1 and 0x11.
|
||||
*/
|
||||
if (LDT_empty(info) || LDT_zero(info))
|
||||
return true;
|
||||
|
||||
/*
|
||||
|
@ -71,7 +92,7 @@ static void set_tls_desc(struct task_struct *p, int idx,
|
|||
cpu = get_cpu();
|
||||
|
||||
while (n-- > 0) {
|
||||
if (LDT_empty(info))
|
||||
if (LDT_empty(info) || LDT_zero(info))
|
||||
desc->a = desc->b = 0;
|
||||
else
|
||||
fill_ldt(desc, info);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue