// SPDX-License-Identifier: GPL-2.0-only
/*
* Resource Director Technology(RDT)
* - Cache Allocation code.
*
* Copyright (C) 2016 Intel Corporation
*
* Authors:
* Fenghua Yu <fenghua.yu@intel.com>
* Tony Luck <tony.luck@intel.com>
* Vikas Shivappa <vikas.shivappa@intel.com>
*
* More information about RDT be found in the Intel (R) x86 Architecture
* Software Developer Manual June 2016, volume 3, section 17.17.
*/
#define pr_fmt(fmt) "resctrl: " fmt
#include <linux/cpu.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/cpuhotplug.h>
#include <asm/cpu_device_id.h>
#include <asm/msr.h>
#include <asm/resctrl.h>
#include "internal.h"
/*
* rdt_domain structures are kfree()d when their last CPU goes offline,
* and allocated when the first CPU in a new domain comes online.
* The rdt_resource's domain list is updated when this happens. Readers of
* the domain list must either take cpus_read_lock(), or rely on an RCU
* read-side critical section, to avoid observing concurrent modification.
* All writers take this mutex:
*/
static DEFINE_MUTEX(domain_list_lock);
/*
* The cached resctrl_pqr_state is strictly per CPU and can never be
* updated from a remote CPU. Functions which modify the state
* are called with interrupts disabled and no preemption, which
* is sufficient for the protection.
*/
DEFINE_PER_CPU(struct resctrl_pqr_state, pqr_state);
/*
* Global boolean for rdt_alloc which is true if any
* resource allocation is enabled.
*/
bool rdt_alloc_capable;
static void mba_wrmsr_intel(struct msr_param *m);
static void cat_wrmsr(struct msr_param *m);
static void mba_wrmsr_amd(struct msr_param *m);
#define ctrl_domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].r_resctrl.ctrl_domains)
#define mon_domain_init(id) LIST_HEAD_INIT(rdt_resources_all[id].r_resctrl.mon_domains)
struct rdt_hw_resource rdt_resources_all[RDT_NUM_RESOURCES] = {
[RDT_RESOURCE_L3] =
{
.r_resctrl = {
.name = "L3",
.ctrl_scope = RESCTRL_L3_CACHE,
.mon_scope = RESCTRL_L3_CACHE,
.ctrl_domains = ctrl_domain_init(RDT_RESOURCE_L3),
.mon_domains = mon_domain_init(RDT_RESOURCE_L3),
.schema_fmt = RESCTRL_SCHEMA_BITMAP,
},
.msr_base = MSR_IA32_L3_CBM_BASE,
.msr_update = cat_wrmsr,
},
[RDT_RESOURCE_L2] =
{
.r_resctrl = {
.name = "L2",
.ctrl_scope = RESCTRL_L2_CACHE,
.ctrl_domains = ctrl_domain_init(RDT_RESOURCE_L2),
.schema_fmt = RESCTRL_SCHEMA_BITMAP,
},
.msr_base = MSR_IA32_L2_CBM_BASE,
.msr_update = cat_wrmsr,
},
[RDT_RESOURCE_MBA] =
{
.r_resctrl = {
.name = "MB",
.ctrl_scope = RESCTRL_L3_CACHE,
.ctrl_domains = ctrl_domain_init(RDT_RESOURCE_MBA),
.schema_fmt = RESCTRL_SCHEMA_RANGE,
},
},
[RDT_RESOURCE_SMBA] =
{
.r_resctrl = {
.name = "SMBA",
.ctrl_scope = RESCTRL_L3_CACHE,
.ctrl_domains = ctrl_domain_init(RDT_RESOURCE_SMBA),
.schema_fmt = RESCTRL_SCHEMA_RANGE,
},
},
[RDT_RESOURCE_PERF_PKG] =
{
.r_resctrl = {
.name = "PERF_PKG",
.mon_scope = RESCTRL_PACKAGE,
.mon_domains = mon_domain_init(RDT_RESOURCE_PERF_PKG),
},
},
};
/**
* resctrl_arch_system_num_rmid_idx - Compute number of supported RMIDs
* (minimum across all mon_capable resource)
*
* Return: Number of supported RMIDs at time of call. Note that mount time
* enumeration of resources may reduce the number.
*/
u32 resctrl_arch_system_num_rmid_idx(void)
{
u32 num_rmids = U32_MAX;
struct rdt_resource *r;
for_each_mon_capable_rdt_resource(r)
num_rmids = min(num_rmids, r->mon.num_rmid);
/* RMID are independent numbers for x86. num_rmid_idx == num_rmid */
return num_rmids == U32_MAX ? 0 : num_rmids;
}
struct rdt_resource *resctrl_arch_get_resource