Skip to content

Commit 8100a58

Browse files
committed
Merge tag 'x86-urgent-2020-12-06' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Thomas Gleixner: "A set of fixes for x86: - Make the AMD L3 QoS code and data priorization enable/disable mechanism work correctly. The control bit was only set/cleared on one of the CPUs in a L3 domain, but it has to be modified on all CPUs in the domain. The initial documentation was not clear about this, but the updated one from Oct 2020 spells it out. - Fix an off by one in the UV platform detection code which causes the UV hubs to be identified wrongly. The chip revisions start at 1 not at 0. - Fix a long standing bug in the evaluation of prefixes in the uprobes code which fails to handle repeated prefixes properly. The aggregate size of the prefixes can be larger than the bytes array but the code blindly iterated over the aggregate size beyond the array boundary. Add a macro to handle this case properly and use it at the affected places" * tag 'x86-urgent-2020-12-06' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/sev-es: Use new for_each_insn_prefix() macro to loop over prefixes bytes x86/insn-eval: Use new for_each_insn_prefix() macro to loop over prefixes bytes x86/uprobes: Do not use prefixes.nbytes when looping over prefixes.bytes x86/platform/uv: Fix UV4 hub revision adjustment x86/resctrl: Fix AMD L3 QOS CDP enable/disable
2 parents 9f6b28d + 84da009 commit 8100a58

File tree

9 files changed

+58
-15
lines changed

9 files changed

+58
-15
lines changed

arch/x86/boot/compressed/sev-es.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,12 @@ struct ghcb *boot_ghcb;
3232
*/
3333
static bool insn_has_rep_prefix(struct insn *insn)
3434
{
35+
insn_byte_t p;
3536
int i;
3637

3738
insn_get_prefixes(insn);
3839

39-
for (i = 0; i < insn->prefixes.nbytes; i++) {
40-
insn_byte_t p = insn->prefixes.bytes[i];
41-
40+
for_each_insn_prefix(insn, i, p) {
4241
if (p == 0xf2 || p == 0xf3)
4342
return true;
4443
}

arch/x86/include/asm/insn.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,21 @@ static inline int insn_offset_immediate(struct insn *insn)
201201
return insn_offset_displacement(insn) + insn->displacement.nbytes;
202202
}
203203

204+
/**
205+
* for_each_insn_prefix() -- Iterate prefixes in the instruction
206+
* @insn: Pointer to struct insn.
207+
* @idx: Index storage.
208+
* @prefix: Prefix byte.
209+
*
210+
* Iterate prefix bytes of given @insn. Each prefix byte is stored in @prefix
211+
* and the index is stored in @idx (note that this @idx is just for a cursor,
212+
* do not change it.)
213+
* Since prefixes.nbytes can be bigger than 4 if some prefixes
214+
* are repeated, it cannot be used for looping over the prefixes.
215+
*/
216+
#define for_each_insn_prefix(insn, idx, prefix) \
217+
for (idx = 0; idx < ARRAY_SIZE(insn->prefixes.bytes) && (prefix = insn->prefixes.bytes[idx]) != 0; idx++)
218+
204219
#define POP_SS_OPCODE 0x1f
205220
#define MOV_SREG_OPCODE 0x8e
206221

arch/x86/kernel/apic/x2apic_uv_x.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ static int __init early_set_hub_type(void)
161161
/* UV4/4A only have a revision difference */
162162
case UV4_HUB_PART_NUMBER:
163163
uv_min_hub_revision_id = node_id.s.revision
164-
+ UV4_HUB_REVISION_BASE;
164+
+ UV4_HUB_REVISION_BASE - 1;
165165
uv_hub_type_set(UV4);
166166
if (uv_min_hub_revision_id == UV4A_HUB_REVISION_BASE)
167167
uv_hub_type_set(UV4|UV4A);

arch/x86/kernel/cpu/resctrl/core.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,8 @@ static void domain_add_cpu(int cpu, struct rdt_resource *r)
570570

571571
if (d) {
572572
cpumask_set_cpu(cpu, &d->cpu_mask);
573+
if (r->cache.arch_has_per_cpu_cfg)
574+
rdt_domain_reconfigure_cdp(r);
573575
return;
574576
}
575577

@@ -923,6 +925,7 @@ static __init void rdt_init_res_defs_intel(void)
923925
r->rid == RDT_RESOURCE_L2CODE) {
924926
r->cache.arch_has_sparse_bitmaps = false;
925927
r->cache.arch_has_empty_bitmaps = false;
928+
r->cache.arch_has_per_cpu_cfg = false;
926929
} else if (r->rid == RDT_RESOURCE_MBA) {
927930
r->msr_base = MSR_IA32_MBA_THRTL_BASE;
928931
r->msr_update = mba_wrmsr_intel;
@@ -943,6 +946,7 @@ static __init void rdt_init_res_defs_amd(void)
943946
r->rid == RDT_RESOURCE_L2CODE) {
944947
r->cache.arch_has_sparse_bitmaps = true;
945948
r->cache.arch_has_empty_bitmaps = true;
949+
r->cache.arch_has_per_cpu_cfg = true;
946950
} else if (r->rid == RDT_RESOURCE_MBA) {
947951
r->msr_base = MSR_IA32_MBA_BW_BASE;
948952
r->msr_update = mba_wrmsr_amd;

arch/x86/kernel/cpu/resctrl/internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,8 @@ struct msr_param {
360360
* executing entities
361361
* @arch_has_sparse_bitmaps: True if a bitmap like f00f is valid.
362362
* @arch_has_empty_bitmaps: True if the '0' bitmap is valid.
363+
* @arch_has_per_cpu_cfg: True if QOS_CFG register for this cache
364+
* level has CPU scope.
363365
*/
364366
struct rdt_cache {
365367
unsigned int cbm_len;
@@ -369,6 +371,7 @@ struct rdt_cache {
369371
unsigned int shareable_bits;
370372
bool arch_has_sparse_bitmaps;
371373
bool arch_has_empty_bitmaps;
374+
bool arch_has_per_cpu_cfg;
372375
};
373376

374377
/**

arch/x86/kernel/cpu/resctrl/rdtgroup.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,8 +1909,13 @@ static int set_cache_qos_cfg(int level, bool enable)
19091909

19101910
r_l = &rdt_resources_all[level];
19111911
list_for_each_entry(d, &r_l->domains, list) {
1912-
/* Pick one CPU from each domain instance to update MSR */
1913-
cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
1912+
if (r_l->cache.arch_has_per_cpu_cfg)
1913+
/* Pick all the CPUs in the domain instance */
1914+
for_each_cpu(cpu, &d->cpu_mask)
1915+
cpumask_set_cpu(cpu, cpu_mask);
1916+
else
1917+
/* Pick one CPU from each domain instance to update MSR */
1918+
cpumask_set_cpu(cpumask_any(&d->cpu_mask), cpu_mask);
19141919
}
19151920
cpu = get_cpu();
19161921
/* Update QOS_CFG MSR on this cpu if it's in cpu_mask. */

arch/x86/kernel/uprobes.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,13 @@ static volatile u32 good_2byte_insns[256 / 32] = {
255255

256256
static bool is_prefix_bad(struct insn *insn)
257257
{
258+
insn_byte_t p;
258259
int i;
259260

260-
for (i = 0; i < insn->prefixes.nbytes; i++) {
261+
for_each_insn_prefix(insn, i, p) {
261262
insn_attr_t attr;
262263

263-
attr = inat_get_opcode_attribute(insn->prefixes.bytes[i]);
264+
attr = inat_get_opcode_attribute(p);
264265
switch (attr) {
265266
case INAT_MAKE_PREFIX(INAT_PFX_ES):
266267
case INAT_MAKE_PREFIX(INAT_PFX_CS):
@@ -715,6 +716,7 @@ static const struct uprobe_xol_ops push_xol_ops = {
715716
static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn)
716717
{
717718
u8 opc1 = OPCODE1(insn);
719+
insn_byte_t p;
718720
int i;
719721

720722
switch (opc1) {
@@ -746,8 +748,8 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn)
746748
* Intel and AMD behavior differ in 64-bit mode: Intel ignores 66 prefix.
747749
* No one uses these insns, reject any branch insns with such prefix.
748750
*/
749-
for (i = 0; i < insn->prefixes.nbytes; i++) {
750-
if (insn->prefixes.bytes[i] == 0x66)
751+
for_each_insn_prefix(insn, i, p) {
752+
if (p == 0x66)
751753
return -ENOTSUPP;
752754
}
753755

arch/x86/lib/insn-eval.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,12 @@ static bool is_string_insn(struct insn *insn)
6363
*/
6464
bool insn_has_rep_prefix(struct insn *insn)
6565
{
66+
insn_byte_t p;
6667
int i;
6768

6869
insn_get_prefixes(insn);
6970

70-
for (i = 0; i < insn->prefixes.nbytes; i++) {
71-
insn_byte_t p = insn->prefixes.bytes[i];
72-
71+
for_each_insn_prefix(insn, i, p) {
7372
if (p == 0xf2 || p == 0xf3)
7473
return true;
7574
}
@@ -95,14 +94,15 @@ static int get_seg_reg_override_idx(struct insn *insn)
9594
{
9695
int idx = INAT_SEG_REG_DEFAULT;
9796
int num_overrides = 0, i;
97+
insn_byte_t p;
9898

9999
insn_get_prefixes(insn);
100100

101101
/* Look for any segment override prefixes. */
102-
for (i = 0; i < insn->prefixes.nbytes; i++) {
102+
for_each_insn_prefix(insn, i, p) {
103103
insn_attr_t attr;
104104

105-
attr = inat_get_opcode_attribute(insn->prefixes.bytes[i]);
105+
attr = inat_get_opcode_attribute(p);
106106
switch (attr) {
107107
case INAT_MAKE_PREFIX(INAT_PFX_CS):
108108
idx = INAT_SEG_REG_CS;

tools/arch/x86/include/asm/insn.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,21 @@ static inline int insn_offset_immediate(struct insn *insn)
201201
return insn_offset_displacement(insn) + insn->displacement.nbytes;
202202
}
203203

204+
/**
205+
* for_each_insn_prefix() -- Iterate prefixes in the instruction
206+
* @insn: Pointer to struct insn.
207+
* @idx: Index storage.
208+
* @prefix: Prefix byte.
209+
*
210+
* Iterate prefix bytes of given @insn. Each prefix byte is stored in @prefix
211+
* and the index is stored in @idx (note that this @idx is just for a cursor,
212+
* do not change it.)
213+
* Since prefixes.nbytes can be bigger than 4 if some prefixes
214+
* are repeated, it cannot be used for looping over the prefixes.
215+
*/
216+
#define for_each_insn_prefix(insn, idx, prefix) \
217+
for (idx = 0; idx < ARRAY_SIZE(insn->prefixes.bytes) && (prefix = insn->prefixes.bytes[idx]) != 0; idx++)
218+
204219
#define POP_SS_OPCODE 0x1f
205220
#define MOV_SREG_OPCODE 0x8e
206221

0 commit comments

Comments
 (0)