summaryrefslogtreecommitdiff
path: root/hw/spapr_rtas.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/spapr_rtas.c')
-rw-r--r--hw/spapr_rtas.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 72268537a8..16b65422b6 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -90,6 +90,81 @@ static void rtas_power_off(sPAPREnvironment *spapr,
rtas_st(rets, 0, 0);
}
+static void rtas_query_cpu_stopped_state(sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ target_ulong id;
+ CPUState *env;
+
+ if (nargs != 1 || nret != 2) {
+ rtas_st(rets, 0, -3);
+ return;
+ }
+
+ id = rtas_ld(args, 0);
+ for (env = first_cpu; env; env = env->next_cpu) {
+ if (env->cpu_index != id) {
+ continue;
+ }
+
+ if (env->halted) {
+ rtas_st(rets, 1, 0);
+ } else {
+ rtas_st(rets, 1, 2);
+ }
+
+ rtas_st(rets, 0, 0);
+ return;
+ }
+
+ /* Didn't find a matching cpu */
+ rtas_st(rets, 0, -3);
+}
+
+static void rtas_start_cpu(sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ target_ulong id, start, r3;
+ CPUState *env;
+
+ if (nargs != 3 || nret != 1) {
+ rtas_st(rets, 0, -3);
+ return;
+ }
+
+ id = rtas_ld(args, 0);
+ start = rtas_ld(args, 1);
+ r3 = rtas_ld(args, 2);
+
+ for (env = first_cpu; env; env = env->next_cpu) {
+ if (env->cpu_index != id) {
+ continue;
+ }
+
+ if (!env->halted) {
+ rtas_st(rets, 0, -1);
+ return;
+ }
+
+ env->msr = (1ULL << MSR_SF) | (1ULL << MSR_ME);
+ env->nip = start;
+ env->gpr[3] = r3;
+ env->halted = 0;
+
+ qemu_cpu_kick(env);
+
+ rtas_st(rets, 0, 0);
+ return;
+ }
+
+ /* Didn't find a matching cpu */
+ rtas_st(rets, 0, -3);
+}
+
static struct rtas_call {
const char *name;
spapr_rtas_fn fn;
@@ -196,5 +271,8 @@ static void register_core_rtas(void)
spapr_rtas_register("display-character", rtas_display_character);
spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
spapr_rtas_register("power-off", rtas_power_off);
+ spapr_rtas_register("query-cpu-stopped-state",
+ rtas_query_cpu_stopped_state);
+ spapr_rtas_register("start-cpu", rtas_start_cpu);
}
device_init(register_core_rtas);