mcctrl: support remote CPU MSR read/write operations
This commit is contained in:
@ -1834,4 +1834,22 @@ mod_nmi_ctx(void *nmi_ctx, void (*func)())
|
|||||||
l[i++] = (unsigned long)(l + 27); // ols rsp
|
l[i++] = (unsigned long)(l + 27); // ols rsp
|
||||||
l[i++] = 0x28; // KERNEL DS
|
l[i++] = 0x28; // KERNEL DS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int arch_cpu_read_write_register(
|
||||||
|
struct mcctrl_os_cpu_register *desc,
|
||||||
|
enum mcctrl_os_cpu_operation op)
|
||||||
|
{
|
||||||
|
if (op == MCCTRL_OS_CPU_READ_REGISTER) {
|
||||||
|
desc->val = rdmsr(desc->addr);
|
||||||
|
}
|
||||||
|
else if (op == MCCTRL_OS_CPU_WRITE_REGISTER) {
|
||||||
|
wrmsr(desc->addr, desc->val);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*** end of file ***/
|
/*** end of file ***/
|
||||||
|
|||||||
@ -40,6 +40,7 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "../../config.h"
|
#include "../../config.h"
|
||||||
#include "mcctrl.h"
|
#include "mcctrl.h"
|
||||||
|
#include "mcctrl_public.h"
|
||||||
#include <ihk/ihk_host_user.h>
|
#include <ihk/ihk_host_user.h>
|
||||||
|
|
||||||
//#define DEBUG
|
//#define DEBUG
|
||||||
@ -1937,3 +1938,149 @@ void mcexec_prepare_ack(ihk_os_t os, unsigned long arg, int err)
|
|||||||
mcctrl_put_per_proc_data(ppd);
|
mcctrl_put_per_proc_data(ppd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Per-CPU register manipulation functions */
|
||||||
|
struct mcctrl_os_cpu_response {
|
||||||
|
int done;
|
||||||
|
unsigned long val;
|
||||||
|
wait_queue_head_t wq;
|
||||||
|
};
|
||||||
|
|
||||||
|
int mcctrl_get_request_os_cpu(ihk_os_t *ret_os, int *ret_cpu)
|
||||||
|
{
|
||||||
|
ihk_os_t os;
|
||||||
|
struct mcctrl_usrdata *usrdata;
|
||||||
|
struct mcctrl_per_proc_data *ppd;
|
||||||
|
struct ikc_scd_packet *packet;
|
||||||
|
struct ihk_ikc_channel_desc *ch;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* Look up IHK OS structure
|
||||||
|
* TODO: iterate all possible indeces, currently only for OS 0
|
||||||
|
*/
|
||||||
|
os = ihk_host_find_os(0, NULL);
|
||||||
|
if (!os) {
|
||||||
|
printk("%s: ERROR: no OS found for index 0\n", __FUNCTION__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look up per-OS mcctrl structure */
|
||||||
|
usrdata = ihk_host_os_get_usrdata(os);
|
||||||
|
if (!usrdata) {
|
||||||
|
printk("%s: ERROR: no usrdata found for OS %p\n", __FUNCTION__, os);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look up per-process structure */
|
||||||
|
ppd = mcctrl_get_per_proc_data(usrdata, task_tgid_vnr(current));
|
||||||
|
if (!ppd) {
|
||||||
|
kprintf("%s: ERROR: no per-process structure for PID %d??\n",
|
||||||
|
__FUNCTION__, task_tgid_vnr(current));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look up per-thread structure */
|
||||||
|
packet = (struct ikc_scd_packet *)mcctrl_get_per_thread_data(ppd, current);
|
||||||
|
if (!packet) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
printk("%s: ERROR: no packet registered for TID %d\n",
|
||||||
|
__FUNCTION__, task_pid_vnr(current));
|
||||||
|
goto out_put_ppd;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ret_os = os;
|
||||||
|
/* TODO: define a new IHK query function instead of
|
||||||
|
* accessing internals directly */
|
||||||
|
ch = (usrdata->channels + packet->ref)->c;
|
||||||
|
*ret_cpu = ch->send.queue->read_cpu;
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
printk("%s: OS: %p, CPU: %d\n", __FUNCTION__, os, *ret_cpu);
|
||||||
|
|
||||||
|
out_put_ppd:
|
||||||
|
mcctrl_put_per_proc_data(ppd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(mcctrl_get_request_os_cpu);
|
||||||
|
|
||||||
|
void mcctrl_os_read_write_cpu_response(ihk_os_t os,
|
||||||
|
struct ikc_scd_packet *pisp)
|
||||||
|
{
|
||||||
|
struct mcctrl_os_cpu_response *resp;
|
||||||
|
|
||||||
|
/* XXX: What if caller thread is unblocked by a signal
|
||||||
|
* before this message arrives? */
|
||||||
|
resp = pisp->resp;
|
||||||
|
if (!resp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resp->val = pisp->desc.val;
|
||||||
|
resp->done = 1;
|
||||||
|
wake_up_interruptible(&resp->wq);
|
||||||
|
}
|
||||||
|
|
||||||
|
int __mcctrl_os_read_write_cpu_register(ihk_os_t os, int cpu,
|
||||||
|
struct mcctrl_os_cpu_register *desc,
|
||||||
|
enum mcctrl_os_cpu_operation op)
|
||||||
|
{
|
||||||
|
struct ikc_scd_packet isp;
|
||||||
|
struct mcctrl_os_cpu_response resp;
|
||||||
|
int ret = -EINVAL;
|
||||||
|
|
||||||
|
memset(&isp, '\0', sizeof(struct ikc_scd_packet));
|
||||||
|
isp.msg = SCD_MSG_CPU_RW_REG;
|
||||||
|
isp.op = op;
|
||||||
|
isp.desc = *desc;
|
||||||
|
isp.resp = &resp;
|
||||||
|
|
||||||
|
resp.done = 0;
|
||||||
|
init_waitqueue_head(&resp.wq);
|
||||||
|
|
||||||
|
mb();
|
||||||
|
ret = mcctrl_ikc_send(os, cpu, &isp);
|
||||||
|
if (ret < 0) {
|
||||||
|
printk("%s: ERROR sending IKC msg: %d\n", __FUNCTION__, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for response */
|
||||||
|
ret = wait_event_interruptible(resp.wq, resp.done);
|
||||||
|
if (ret < 0) {
|
||||||
|
printk("%s: ERROR after wait: %d\n", __FUNCTION__, ret);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update if read */
|
||||||
|
if (ret == 0 && op == MCCTRL_OS_CPU_READ_REGISTER) {
|
||||||
|
desc->val = resp.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
printk("%s: MCCTRL_OS_CPU_%s_REGISTER: reg: 0x%lx, val: 0x%lx\n",
|
||||||
|
__FUNCTION__,
|
||||||
|
(op == MCCTRL_OS_CPU_READ_REGISTER ? "READ" : "WRITE"),
|
||||||
|
desc->addr, desc->val);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mcctrl_os_read_cpu_register(ihk_os_t os, int cpu,
|
||||||
|
struct mcctrl_os_cpu_register *desc)
|
||||||
|
{
|
||||||
|
return __mcctrl_os_read_write_cpu_register(os, cpu,
|
||||||
|
desc, MCCTRL_OS_CPU_READ_REGISTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(mcctrl_os_read_cpu_register);
|
||||||
|
|
||||||
|
int mcctrl_os_write_cpu_register(ihk_os_t os, int cpu,
|
||||||
|
struct mcctrl_os_cpu_register *desc)
|
||||||
|
{
|
||||||
|
return __mcctrl_os_read_write_cpu_register(os, cpu,
|
||||||
|
desc, MCCTRL_OS_CPU_WRITE_REGISTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(mcctrl_os_write_cpu_register);
|
||||||
|
|
||||||
|
|||||||
@ -54,6 +54,8 @@ static void mcctrl_ikc_init(ihk_os_t os, int cpu, unsigned long rphys, struct ih
|
|||||||
int mcexec_syscall(struct mcctrl_usrdata *ud, struct ikc_scd_packet *packet);
|
int mcexec_syscall(struct mcctrl_usrdata *ud, struct ikc_scd_packet *packet);
|
||||||
void sig_done(unsigned long arg, int err);
|
void sig_done(unsigned long arg, int err);
|
||||||
void mcctrl_perf_ack(ihk_os_t os, struct ikc_scd_packet *packet);
|
void mcctrl_perf_ack(ihk_os_t os, struct ikc_scd_packet *packet);
|
||||||
|
void mcctrl_os_read_write_cpu_response(ihk_os_t os,
|
||||||
|
struct ikc_scd_packet *pisp);
|
||||||
|
|
||||||
/* XXX: this runs in atomic context! */
|
/* XXX: this runs in atomic context! */
|
||||||
static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
|
static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
|
||||||
@ -113,6 +115,11 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
|
|||||||
case SCD_MSG_PERF_ACK:
|
case SCD_MSG_PERF_ACK:
|
||||||
mcctrl_perf_ack(__os, pisp);
|
mcctrl_perf_ack(__os, pisp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SCD_MSG_CPU_RW_REG_RESP:
|
||||||
|
mcctrl_os_read_write_cpu_response(__os, pisp);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
printk(KERN_ERR "mcctrl:syscall_packet_handler:"
|
printk(KERN_ERR "mcctrl:syscall_packet_handler:"
|
||||||
"unknown message (%d.%d.%d.%d.%d.%#lx)\n",
|
"unknown message (%d.%d.%d.%d.%d.%#lx)\n",
|
||||||
|
|||||||
@ -44,6 +44,7 @@
|
|||||||
#include <linux/rwlock.h>
|
#include <linux/rwlock.h>
|
||||||
#include <linux/threads.h>
|
#include <linux/threads.h>
|
||||||
#include "sysfs.h"
|
#include "sysfs.h"
|
||||||
|
#include "mcctrl_public.h"
|
||||||
|
|
||||||
#define SCD_MSG_PREPARE_PROCESS 0x1
|
#define SCD_MSG_PREPARE_PROCESS 0x1
|
||||||
#define SCD_MSG_PREPARE_PROCESS_ACKED 0x2
|
#define SCD_MSG_PREPARE_PROCESS_ACKED 0x2
|
||||||
@ -95,6 +96,9 @@
|
|||||||
#define SCD_MSG_PERF_CTRL 0x50
|
#define SCD_MSG_PERF_CTRL 0x50
|
||||||
#define SCD_MSG_PERF_ACK 0x51
|
#define SCD_MSG_PERF_ACK 0x51
|
||||||
|
|
||||||
|
#define SCD_MSG_CPU_RW_REG 0x52
|
||||||
|
#define SCD_MSG_CPU_RW_REG_RESP 0x53
|
||||||
|
|
||||||
#define DMA_PIN_SHIFT 21
|
#define DMA_PIN_SHIFT 21
|
||||||
|
|
||||||
#define DO_USER_MODE
|
#define DO_USER_MODE
|
||||||
@ -106,6 +110,12 @@ struct coretable {
|
|||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum mcctrl_os_cpu_operation {
|
||||||
|
MCCTRL_OS_CPU_READ_REGISTER,
|
||||||
|
MCCTRL_OS_CPU_WRITE_REGISTER,
|
||||||
|
MCCTRL_OS_CPU_MAX_OP
|
||||||
|
};
|
||||||
|
|
||||||
struct ikc_scd_packet {
|
struct ikc_scd_packet {
|
||||||
int msg;
|
int msg;
|
||||||
int err;
|
int err;
|
||||||
@ -131,6 +141,13 @@ struct ikc_scd_packet {
|
|||||||
struct {
|
struct {
|
||||||
int ttid;
|
int ttid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* SCD_MSG_CPU_RW_REG */
|
||||||
|
struct {
|
||||||
|
struct mcctrl_os_cpu_register desc;
|
||||||
|
enum mcctrl_os_cpu_operation op;
|
||||||
|
void *resp;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
char padding[12];
|
char padding[12];
|
||||||
};
|
};
|
||||||
|
|||||||
20
executer/kernel/mcctrl/mcctrl_public.h
Normal file
20
executer/kernel/mcctrl/mcctrl_public.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef __MCCTRL_PUBLIC_H
|
||||||
|
#define __MCCTRL_PUBLIC_H
|
||||||
|
|
||||||
|
#include <ihk/ihk_host_user.h>
|
||||||
|
#include <ikc/queue.h>
|
||||||
|
|
||||||
|
struct mcctrl_os_cpu_register {
|
||||||
|
unsigned long addr;
|
||||||
|
unsigned long val;
|
||||||
|
unsigned long addr_ext;
|
||||||
|
};
|
||||||
|
|
||||||
|
int mcctrl_os_read_cpu_register(ihk_os_t os, int cpu,
|
||||||
|
struct mcctrl_os_cpu_register *desc);
|
||||||
|
int mcctrl_os_write_cpu_register(ihk_os_t os, int cpu,
|
||||||
|
struct mcctrl_os_cpu_register *desc);
|
||||||
|
int mcctrl_get_request_os_cpu(ihk_os_t *os, int *cpu);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __MCCTRL_PUBLIC_H
|
||||||
@ -644,6 +644,17 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c,
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SCD_MSG_CPU_RW_REG:
|
||||||
|
|
||||||
|
pckt.msg = SCD_MSG_CPU_RW_REG_RESP;
|
||||||
|
memcpy(&pckt.desc, &packet->desc,
|
||||||
|
sizeof(struct mcctrl_os_cpu_register));
|
||||||
|
pckt.resp = packet->resp;
|
||||||
|
pckt.err = arch_cpu_read_write_register(&pckt.desc, pckt.op);
|
||||||
|
|
||||||
|
ihk_ikc_send(resp_channel, &pckt, 0);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
kprintf("syscall_pakcet_handler:unknown message "
|
kprintf("syscall_pakcet_handler:unknown message "
|
||||||
"(%d.%d.%d.%d.%d.%#lx)\n",
|
"(%d.%d.%d.%d.%d.%#lx)\n",
|
||||||
|
|||||||
@ -78,6 +78,9 @@
|
|||||||
#define SCD_MSG_PERF_CTRL 0x50
|
#define SCD_MSG_PERF_CTRL 0x50
|
||||||
#define SCD_MSG_PERF_ACK 0x51
|
#define SCD_MSG_PERF_ACK 0x51
|
||||||
|
|
||||||
|
#define SCD_MSG_CPU_RW_REG 0x52
|
||||||
|
#define SCD_MSG_CPU_RW_REG_RESP 0x53
|
||||||
|
|
||||||
/* Cloning flags. */
|
/* Cloning flags. */
|
||||||
# define CSIGNAL 0x000000ff /* Signal mask to be sent at exit. */
|
# define CSIGNAL 0x000000ff /* Signal mask to be sent at exit. */
|
||||||
# define CLONE_VM 0x00000100 /* Set if VM shared between processes. */
|
# define CLONE_VM 0x00000100 /* Set if VM shared between processes. */
|
||||||
@ -210,6 +213,18 @@ struct syscall_request {
|
|||||||
unsigned long args[6];
|
unsigned long args[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct mcctrl_os_cpu_register {
|
||||||
|
unsigned long addr;
|
||||||
|
unsigned long val;
|
||||||
|
unsigned long addr_ext;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum mcctrl_os_cpu_operation {
|
||||||
|
MCCTRL_OS_CPU_READ_REGISTER,
|
||||||
|
MCCTRL_OS_CPU_WRITE_REGISTER,
|
||||||
|
MCCTRL_OS_CPU_MAX_OP
|
||||||
|
};
|
||||||
|
|
||||||
struct ikc_scd_packet {
|
struct ikc_scd_packet {
|
||||||
int msg;
|
int msg;
|
||||||
int err;
|
int err;
|
||||||
@ -235,6 +250,13 @@ struct ikc_scd_packet {
|
|||||||
struct {
|
struct {
|
||||||
int ttid;
|
int ttid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* SCD_MSG_CPU_RW_REG */
|
||||||
|
struct {
|
||||||
|
struct mcctrl_os_cpu_register desc;
|
||||||
|
enum mcctrl_os_cpu_operation op;
|
||||||
|
void *resp;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
char padding[12];
|
char padding[12];
|
||||||
};
|
};
|
||||||
@ -412,6 +434,8 @@ int do_shmget(key_t key, size_t size, int shmflg);
|
|||||||
struct process_vm;
|
struct process_vm;
|
||||||
int arch_map_vdso(struct process_vm *vm); /* arch dependent */
|
int arch_map_vdso(struct process_vm *vm); /* arch dependent */
|
||||||
int arch_setup_vdso(void);
|
int arch_setup_vdso(void);
|
||||||
|
int arch_cpu_read_write_register(struct mcctrl_os_cpu_register *desc,
|
||||||
|
enum mcctrl_os_cpu_operation op);
|
||||||
|
|
||||||
#define VDSO_MAXPAGES 2
|
#define VDSO_MAXPAGES 2
|
||||||
struct vdso {
|
struct vdso {
|
||||||
|
|||||||
Reference in New Issue
Block a user