@@ -34,6 +34,7 @@
#include <xen/xenoprof.h>
#include <xen/irq.h>
#include <xen/argo.h>
+#include <xen/llc-coloring.h>
#include <asm/p2m.h>
#include <asm/processor.h>
#include <public/sched.h>
@@ -1276,6 +1277,8 @@ void domain_destroy(struct domain *d)
{
BUG_ON(!d->is_dying);
+ domain_llc_coloring_free(d);
+
/* May be already destroyed, or get_domain() can race us. */
if ( atomic_cmpxchg(&d->refcnt, 0, DOMAIN_DESTROYED) != 0 )
return;
@@ -8,6 +8,7 @@
#include <xen/types.h>
#include <xen/lib.h>
+#include <xen/llc-coloring.h>
#include <xen/err.h>
#include <xen/mm.h>
#include <xen/sched.h>
@@ -866,6 +867,15 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
__HYPERVISOR_domctl, "h", u_domctl);
break;
+ case XEN_DOMCTL_set_llc_colors:
+ if ( op->u.set_llc_colors.pad )
+ ret = -EINVAL;
+ else if ( llc_coloring_enabled )
+ ret = domain_set_llc_colors(d, &op->u.set_llc_colors);
+ else
+ ret = -EOPNOTSUPP;
+ break;
+
default:
ret = arch_do_domctl(op, d, u_domctl);
break;
@@ -5,6 +5,7 @@
* Copyright (C) 2024, Advanced Micro Devices, Inc.
* Copyright (C) 2024, Minerva Systems SRL
*/
+#include <xen/guest_access.h>
#include <xen/keyhandler.h>
#include <xen/llc-coloring.h>
#include <xen/param.h>
@@ -104,8 +105,7 @@ static void print_colors(const unsigned int colors[], unsigned int num_colors)
printk(" }\n");
}
-static bool __init check_colors(const unsigned int colors[],
- unsigned int num_colors)
+static bool check_colors(const unsigned int colors[], unsigned int num_colors)
{
unsigned int i;
@@ -184,7 +184,7 @@ void domain_dump_llc_colors(const struct domain *d)
print_colors(d->llc_colors, d->num_llc_colors);
}
-static void __init domain_set_default_colors(struct domain *d)
+static void domain_set_default_colors(struct domain *d)
{
printk(XENLOG_WARNING
"LLC color config not found for %pd, using all colors\n", d);
@@ -221,6 +221,55 @@ int __init dom0_set_llc_colors(struct domain *d)
return 0;
}
+int domain_set_llc_colors(struct domain *d,
+ const struct xen_domctl_set_llc_colors *config)
+{
+ unsigned int *colors;
+
+ if ( d->num_llc_colors )
+ return -EEXIST;
+
+ if ( !config->num_llc_colors )
+ {
+ domain_set_default_colors(d);
+ return 0;
+ }
+
+ if ( config->num_llc_colors > max_nr_colors )
+ return -EINVAL;
+
+ colors = xmalloc_array(unsigned int, config->num_llc_colors);
+ if ( !colors )
+ return -ENOMEM;
+
+ if ( copy_from_guest(colors, config->llc_colors, config->num_llc_colors) )
+ {
+ xfree(colors);
+ return -EFAULT;
+ }
+
+ if ( !check_colors(colors, config->num_llc_colors) )
+ {
+ printk(XENLOG_ERR "%pd: bad LLC color config\n", d);
+ xfree(colors);
+ return -EINVAL;
+ }
+
+ d->llc_colors = colors;
+ d->num_llc_colors = config->num_llc_colors;
+
+ return 0;
+}
+
+void domain_llc_coloring_free(struct domain *d)
+{
+ if ( !llc_coloring_enabled || d->llc_colors == default_colors )
+ return;
+
+ /* free pointer-to-const using __va(__pa()) */
+ xfree(__va(__pa(d->llc_colors)));
+}
+
/*
* Local variables:
* mode: C
@@ -1236,6 +1236,13 @@ struct xen_domctl_dt_overlay {
};
#endif
+struct xen_domctl_set_llc_colors {
+ /* IN LLC coloring parameters */
+ uint32_t num_llc_colors;
+ uint32_t pad;
+ XEN_GUEST_HANDLE_64(uint32) llc_colors;
+};
+
struct xen_domctl {
uint32_t cmd;
#define XEN_DOMCTL_createdomain 1
@@ -1325,6 +1332,7 @@ struct xen_domctl {
#define XEN_DOMCTL_set_paging_mempool_size 86
#define XEN_DOMCTL_dt_overlay 87
#define XEN_DOMCTL_gsi_permission 88
+#define XEN_DOMCTL_set_llc_colors 89
#define XEN_DOMCTL_gdbsx_guestmemio 1000
#define XEN_DOMCTL_gdbsx_pausevcpu 1001
#define XEN_DOMCTL_gdbsx_unpausevcpu 1002
@@ -1391,6 +1399,7 @@ struct xen_domctl {
#if defined(__arm__) || defined(__aarch64__)
struct xen_domctl_dt_overlay dt_overlay;
#endif
+ struct xen_domctl_set_llc_colors set_llc_colors;
uint8_t pad[128];
} u;
};
@@ -17,17 +17,21 @@ extern bool llc_coloring_enabled;
void llc_coloring_init(void);
void dump_llc_coloring_info(void);
void domain_dump_llc_colors(const struct domain *d);
+void domain_llc_coloring_free(struct domain *d);
#else
#define llc_coloring_enabled false
static inline void llc_coloring_init(void) {}
static inline void dump_llc_coloring_info(void) {}
static inline void domain_dump_llc_colors(const struct domain *d) {}
+static inline void domain_llc_coloring_free(struct domain *d) {}
#endif
unsigned int get_llc_way_size(void);
void arch_llc_coloring_init(void);
int dom0_set_llc_colors(struct domain *d);
+int domain_set_llc_colors(struct domain *d,
+ const struct xen_domctl_set_llc_colors *config);
#endif /* __COLORING_H__ */