Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 234843
b: refs/heads/master
c: cabb5bd
h: refs/heads/master
i:
  234841: 82c3107
  234839: 0611525
v: v3
  • Loading branch information
Hans Rosenfeld authored and Ingo Molnar committed Feb 7, 2011
1 parent c0800cd commit cdb5a67
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 41b2610c3443e6c4760e61fc10eef73f96f9f6a5
refs/heads/master: cabb5bd7ff4d6963ec9e67f958fc30e7815425e6
3 changes: 3 additions & 0 deletions trunk/arch/x86/include/asm/amd_nb.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ extern int amd_cache_northbridges(void);
extern void amd_flush_garts(void);
extern int amd_numa_init(unsigned long start_pfn, unsigned long end_pfn);
extern int amd_scan_nodes(void);
extern int amd_get_subcaches(int);
extern int amd_set_subcaches(int, int);

#ifdef CONFIG_NUMA_EMU
extern void amd_fake_nodes(const struct bootnode *nodes, int nr_nodes);
Expand All @@ -38,6 +40,7 @@ extern struct amd_northbridge_info amd_northbridges;

#define AMD_NB_GART 0x1
#define AMD_NB_L3_INDEX_DISABLE 0x2
#define AMD_NB_L3_PARTITIONING 0x4

#ifdef CONFIG_AMD_NB

Expand Down
63 changes: 63 additions & 0 deletions trunk/arch/x86/kernel/amd_nb.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ int amd_cache_northbridges(void)
if (boot_cpu_data.x86 == 0x15)
amd_northbridges.flags |= AMD_NB_L3_INDEX_DISABLE;

/* L3 cache partitioning is supported on family 0x15 */
if (boot_cpu_data.x86 == 0x15)
amd_northbridges.flags |= AMD_NB_L3_PARTITIONING;

return 0;
}
EXPORT_SYMBOL_GPL(amd_cache_northbridges);
Expand All @@ -112,6 +116,65 @@ int __init early_is_amd_nb(u32 device)
return 0;
}

int amd_get_subcaches(int cpu)
{
struct pci_dev *link = node_to_amd_nb(amd_get_nb_id(cpu))->link;
unsigned int mask;
int cuid = 0;

if (!amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
return 0;

pci_read_config_dword(link, 0x1d4, &mask);

#ifdef CONFIG_SMP
cuid = cpu_data(cpu).compute_unit_id;
#endif
return (mask >> (4 * cuid)) & 0xf;
}

int amd_set_subcaches(int cpu, int mask)
{
static unsigned int reset, ban;
struct amd_northbridge *nb = node_to_amd_nb(amd_get_nb_id(cpu));
unsigned int reg;
int cuid = 0;

if (!amd_nb_has_feature(AMD_NB_L3_PARTITIONING) || mask > 0xf)
return -EINVAL;

/* if necessary, collect reset state of L3 partitioning and BAN mode */
if (reset == 0) {
pci_read_config_dword(nb->link, 0x1d4, &reset);
pci_read_config_dword(nb->misc, 0x1b8, &ban);
ban &= 0x180000;
}

/* deactivate BAN mode if any subcaches are to be disabled */
if (mask != 0xf) {
pci_read_config_dword(nb->misc, 0x1b8, &reg);
pci_write_config_dword(nb->misc, 0x1b8, reg & ~0x180000);
}

#ifdef CONFIG_SMP
cuid = cpu_data(cpu).compute_unit_id;
#endif
mask <<= 4 * cuid;
mask |= (0xf ^ (1 << cuid)) << 26;

pci_write_config_dword(nb->link, 0x1d4, mask);

/* reset BAN mode if L3 partitioning returned to reset state */
pci_read_config_dword(nb->link, 0x1d4, &reg);
if (reg == reset) {
pci_read_config_dword(nb->misc, 0x1b8, &reg);
reg &= ~0x180000;
pci_write_config_dword(nb->misc, 0x1b8, reg | ban);
}

return 0;
}

int amd_cache_gart(void)
{
int i;
Expand Down
76 changes: 61 additions & 15 deletions trunk/arch/x86/kernel/cpu/intel_cacheinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,9 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax,

struct _cache_attr {
struct attribute attr;
ssize_t (*show)(struct _cpuid4_info *, char *);
ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
ssize_t (*show)(struct _cpuid4_info *, char *, unsigned int);
ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count,
unsigned int);
};

#ifdef CONFIG_AMD_NB
Expand Down Expand Up @@ -400,7 +401,8 @@ static ssize_t show_cache_disable(struct _cpuid4_info *this_leaf, char *buf,

#define SHOW_CACHE_DISABLE(slot) \
static ssize_t \
show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf) \
show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf, \
unsigned int cpu) \
{ \
return show_cache_disable(this_leaf, buf, slot); \
}
Expand Down Expand Up @@ -512,7 +514,8 @@ static ssize_t store_cache_disable(struct _cpuid4_info *this_leaf,
#define STORE_CACHE_DISABLE(slot) \
static ssize_t \
store_cache_disable_##slot(struct _cpuid4_info *this_leaf, \
const char *buf, size_t count) \
const char *buf, size_t count, \
unsigned int cpu) \
{ \
return store_cache_disable(this_leaf, buf, count, slot); \
}
Expand All @@ -524,6 +527,39 @@ static struct _cache_attr cache_disable_0 = __ATTR(cache_disable_0, 0644,
static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
show_cache_disable_1, store_cache_disable_1);

static ssize_t
show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu)
{
if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
return -EINVAL;

return sprintf(buf, "%x\n", amd_get_subcaches(cpu));
}

static ssize_t
store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count,
unsigned int cpu)
{
unsigned long val;

if (!capable(CAP_SYS_ADMIN))
return -EPERM;

if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
return -EINVAL;

if (strict_strtoul(buf, 16, &val) < 0)
return -EINVAL;

if (amd_set_subcaches(cpu, val))
return -EINVAL;

return count;
}

static struct _cache_attr subcaches =
__ATTR(subcaches, 0644, show_subcaches, store_subcaches);

#else /* CONFIG_AMD_NB */
#define amd_init_l3_cache(x, y)
#endif /* CONFIG_AMD_NB */
Expand All @@ -532,9 +568,9 @@ static int
__cpuinit cpuid4_cache_lookup_regs(int index,
struct _cpuid4_info_regs *this_leaf)
{
union _cpuid4_leaf_eax eax;
union _cpuid4_leaf_ebx ebx;
union _cpuid4_leaf_ecx ecx;
union _cpuid4_leaf_eax eax;
union _cpuid4_leaf_ebx ebx;
union _cpuid4_leaf_ecx ecx;
unsigned edx;

if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
Expand Down Expand Up @@ -870,8 +906,8 @@ static DEFINE_PER_CPU(struct _index_kobject *, ici_index_kobject);
#define INDEX_KOBJECT_PTR(x, y) (&((per_cpu(ici_index_kobject, x))[y]))

#define show_one_plus(file_name, object, val) \
static ssize_t show_##file_name \
(struct _cpuid4_info *this_leaf, char *buf) \
static ssize_t show_##file_name(struct _cpuid4_info *this_leaf, char *buf, \
unsigned int cpu) \
{ \
return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \
}
Expand All @@ -882,7 +918,8 @@ show_one_plus(physical_line_partition, ebx.split.physical_line_partition, 1);
show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1);
show_one_plus(number_of_sets, ecx.split.number_of_sets, 1);

static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf)
static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf,
unsigned int cpu)
{
return sprintf(buf, "%luK\n", this_leaf->size / 1024);
}
Expand All @@ -906,17 +943,20 @@ static ssize_t show_shared_cpu_map_func(struct _cpuid4_info *this_leaf,
return n;
}

static inline ssize_t show_shared_cpu_map(struct _cpuid4_info *leaf, char *buf)
static inline ssize_t show_shared_cpu_map(struct _cpuid4_info *leaf, char *buf,
unsigned int cpu)
{
return show_shared_cpu_map_func(leaf, 0, buf);
}

static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf)
static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf,
unsigned int cpu)
{
return show_shared_cpu_map_func(leaf, 1, buf);
}

static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf)
static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf,
unsigned int cpu)
{
switch (this_leaf->eax.split.type) {
case CACHE_TYPE_DATA:
Expand Down Expand Up @@ -974,6 +1014,9 @@ static struct attribute ** __cpuinit amd_l3_attrs(void)
if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
n += 2;

if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
n += 1;

attrs = kzalloc(n * sizeof (struct attribute *), GFP_KERNEL);
if (attrs == NULL)
return attrs = default_attrs;
Expand All @@ -986,6 +1029,9 @@ static struct attribute ** __cpuinit amd_l3_attrs(void)
attrs[n++] = &cache_disable_1.attr;
}

if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
attrs[n++] = &subcaches.attr;

return attrs;
}
#endif
Expand All @@ -998,7 +1044,7 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)

ret = fattr->show ?
fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
buf) :
buf, this_leaf->cpu) :
0;
return ret;
}
Expand All @@ -1012,7 +1058,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,

ret = fattr->store ?
fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
buf, count) :
buf, count, this_leaf->cpu) :
0;
return ret;
}
Expand Down

0 comments on commit cdb5a67

Please sign in to comment.