Skip to content

Commit

Permalink
spapr: Fix RTAS token numbers
Browse files Browse the repository at this point in the history
At the moment spapr_rtas_register() allocates a new token number for every
new RTAS callback so numbers are not fixed and depend on the number of
supported RTAS handlers and the exact order of spapr_rtas_register() calls.
These tokens are copied into the device tree and remain the same during
the guest lifetime.

When we start another guest to receive a migration, it calls
spapr_rtas_register() as well. If the number of RTAS handlers or their
order is different in QEMU on source and destination sides, the "/rtas"
node in the device tree will differ. Since migration overwrites the device
tree (as it overwrites the entire RAM), the actual RTAS config on
the destination side gets broken.

This defines global contant values for every RTAS token which QEMU
is using today.

This changes spapr_rtas_register() to accept a token number instead of
allocating one. This changes all users of spapr_rtas_register().

This changes XICS-KVM not to cache tokens registered with KVM as they
constant now.

This makes TOKEN_BASE global as RTAS_XXX use TOKEN_BASE as
a base. TOKEN_MAX is moved and renamed too and its value is changed
to the last token + 1. Boundary checks for token values are adjusted.

This reserves token numbers for "os-term" handlers and PCI hotplug
which we are working on.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Alexander Graf <agraf@suse.de>
  • Loading branch information
aik authored and agraf committed Jun 27, 2014
1 parent b3cad3a commit 3a3b850
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 64 deletions.
8 changes: 4 additions & 4 deletions hw/intc/xics.c
Expand Up @@ -866,10 +866,10 @@ static void xics_realize(DeviceState *dev, Error **errp)
}

/* Registration of global state belongs into realize */
spapr_rtas_register("ibm,set-xive", rtas_set_xive);
spapr_rtas_register("ibm,get-xive", rtas_get_xive);
spapr_rtas_register("ibm,int-off", rtas_int_off);
spapr_rtas_register("ibm,int-on", rtas_int_on);
spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_set_xive);
spapr_rtas_register(RTAS_IBM_GET_XIVE, "ibm,get-xive", rtas_get_xive);
spapr_rtas_register(RTAS_IBM_INT_OFF, "ibm,int-off", rtas_int_off);
spapr_rtas_register(RTAS_IBM_INT_ON, "ibm,int-on", rtas_int_on);

spapr_register_hypercall(H_CPPR, h_cppr);
spapr_register_hypercall(H_IPI, h_ipi);
Expand Down
22 changes: 8 additions & 14 deletions hw/intc/xics_kvm.c
Expand Up @@ -38,10 +38,6 @@
typedef struct KVMXICSState {
XICSState parent_obj;

uint32_t set_xive_token;
uint32_t get_xive_token;
uint32_t int_off_token;
uint32_t int_on_token;
int kernel_xics_fd;
} KVMXICSState;

Expand Down Expand Up @@ -392,32 +388,30 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
goto fail;
}

icpkvm->set_xive_token = spapr_rtas_register("ibm,set-xive", rtas_dummy);
icpkvm->get_xive_token = spapr_rtas_register("ibm,get-xive", rtas_dummy);
icpkvm->int_off_token = spapr_rtas_register("ibm,int-off", rtas_dummy);
icpkvm->int_on_token = spapr_rtas_register("ibm,int-on", rtas_dummy);
spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_dummy);
spapr_rtas_register(RTAS_IBM_GET_XIVE, "ibm,get-xive", rtas_dummy);
spapr_rtas_register(RTAS_IBM_INT_OFF, "ibm,int-off", rtas_dummy);
spapr_rtas_register(RTAS_IBM_INT_ON, "ibm,int-on", rtas_dummy);

rc = kvmppc_define_rtas_kernel_token(icpkvm->set_xive_token,
"ibm,set-xive");
rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_SET_XIVE, "ibm,set-xive");
if (rc < 0) {
error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,set-xive");
goto fail;
}

rc = kvmppc_define_rtas_kernel_token(icpkvm->get_xive_token,
"ibm,get-xive");
rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_GET_XIVE, "ibm,get-xive");
if (rc < 0) {
error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,get-xive");
goto fail;
}

rc = kvmppc_define_rtas_kernel_token(icpkvm->int_on_token, "ibm,int-on");
rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_INT_ON, "ibm,int-on");
if (rc < 0) {
error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,int-on");
goto fail;
}

rc = kvmppc_define_rtas_kernel_token(icpkvm->int_off_token, "ibm,int-off");
rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_INT_OFF, "ibm,int-off");
if (rc < 0) {
error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,int-off");
goto fail;
Expand Down
4 changes: 2 additions & 2 deletions hw/nvram/spapr_nvram.c
Expand Up @@ -153,8 +153,8 @@ static int spapr_nvram_init(VIOsPAPRDevice *dev)
return -1;
}

spapr_rtas_register("nvram-fetch", rtas_nvram_fetch);
spapr_rtas_register("nvram-store", rtas_nvram_store);
spapr_rtas_register(RTAS_NVRAM_FETCH, "nvram-fetch", rtas_nvram_fetch);
spapr_rtas_register(RTAS_NVRAM_STORE, "nvram-store", rtas_nvram_store);

return 0;
}
Expand Down
3 changes: 2 additions & 1 deletion hw/ppc/spapr_events.c
Expand Up @@ -317,5 +317,6 @@ void spapr_events_init(sPAPREnvironment *spapr)
spapr->epow_irq = spapr_allocate_msi(0);
spapr->epow_notifier.notify = spapr_powerdown_req;
qemu_register_powerdown_notifier(&spapr->epow_notifier);
spapr_rtas_register("check-exception", check_exception);
spapr_rtas_register(RTAS_CHECK_EXCEPTION, "check-exception",
check_exception);
}
18 changes: 12 additions & 6 deletions hw/ppc/spapr_pci.c
Expand Up @@ -909,14 +909,20 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,

void spapr_pci_rtas_init(void)
{
spapr_rtas_register("read-pci-config", rtas_read_pci_config);
spapr_rtas_register("write-pci-config", rtas_write_pci_config);
spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config);
spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config);
spapr_rtas_register(RTAS_READ_PCI_CONFIG, "read-pci-config",
rtas_read_pci_config);
spapr_rtas_register(RTAS_WRITE_PCI_CONFIG, "write-pci-config",
rtas_write_pci_config);
spapr_rtas_register(RTAS_IBM_READ_PCI_CONFIG, "ibm,read-pci-config",
rtas_ibm_read_pci_config);
spapr_rtas_register(RTAS_IBM_WRITE_PCI_CONFIG, "ibm,write-pci-config",
rtas_ibm_write_pci_config);
if (msi_supported) {
spapr_rtas_register("ibm,query-interrupt-source-number",
spapr_rtas_register(RTAS_IBM_QUERY_INTERRUPT_SOURCE_NUMBER,
"ibm,query-interrupt-source-number",
rtas_ibm_query_interrupt_source_number);
spapr_rtas_register("ibm,change-msi", rtas_ibm_change_msi);
spapr_rtas_register(RTAS_IBM_CHANGE_MSI, "ibm,change-msi",
rtas_ibm_change_msi);
}
}

Expand Down
67 changes: 33 additions & 34 deletions hw/ppc/spapr_rtas.c
Expand Up @@ -36,9 +36,6 @@

#include <libfdt.h>

#define TOKEN_BASE 0x2000
#define TOKEN_MAX 0x100

static void rtas_display_character(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t token, uint32_t nargs,
target_ulong args,
Expand Down Expand Up @@ -271,17 +268,14 @@ static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu,
static struct rtas_call {
const char *name;
spapr_rtas_fn fn;
} rtas_table[TOKEN_MAX];

static struct rtas_call *rtas_next = rtas_table;
} rtas_table[RTAS_TOKEN_MAX - RTAS_TOKEN_BASE];

target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t token, uint32_t nargs, target_ulong args,
uint32_t nret, target_ulong rets)
{
if ((token >= TOKEN_BASE)
&& ((token - TOKEN_BASE) < TOKEN_MAX)) {
struct rtas_call *call = rtas_table + (token - TOKEN_BASE);
if ((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX)) {
struct rtas_call *call = rtas_table + (token - RTAS_TOKEN_BASE);

if (call->fn) {
call->fn(cpu, spapr, token, nargs, args, nret, rets);
Expand All @@ -303,23 +297,22 @@ target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPREnvironment *spapr,
return H_PARAMETER;
}

int spapr_rtas_register(const char *name, spapr_rtas_fn fn)
void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn)
{
int i;

for (i = 0; i < (rtas_next - rtas_table); i++) {
if (strcmp(name, rtas_table[i].name) == 0) {
fprintf(stderr, "RTAS call \"%s\" registered twice\n", name);
exit(1);
}
if (!((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX))) {
fprintf(stderr, "RTAS invalid token 0x%x\n", token);
exit(1);
}

assert(rtas_next < (rtas_table + TOKEN_MAX));

rtas_next->name = name;
rtas_next->fn = fn;
token -= RTAS_TOKEN_BASE;
if (rtas_table[token].name) {
fprintf(stderr, "RTAS call \"%s\" is registered already as 0x%x\n",
rtas_table[token].name, token);
exit(1);
}

return (rtas_next++ - rtas_table) + TOKEN_BASE;
rtas_table[token].name = name;
rtas_table[token].fn = fn;
}

int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
Expand Down Expand Up @@ -359,15 +352,15 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
return ret;
}

for (i = 0; i < TOKEN_MAX; i++) {
for (i = 0; i < RTAS_TOKEN_MAX - RTAS_TOKEN_BASE; i++) {
struct rtas_call *call = &rtas_table[i];

if (!call->name) {
continue;
}

ret = qemu_fdt_setprop_cell(fdt, "/rtas", call->name,
i + TOKEN_BASE);
i + RTAS_TOKEN_BASE);
if (ret < 0) {
fprintf(stderr, "Couldn't add rtas token for %s: %s\n",
call->name, fdt_strerror(ret));
Expand All @@ -380,18 +373,24 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,

static void core_rtas_register_types(void)
{
spapr_rtas_register("display-character", rtas_display_character);
spapr_rtas_register("get-time-of-day", rtas_get_time_of_day);
spapr_rtas_register("set-time-of-day", rtas_set_time_of_day);
spapr_rtas_register("power-off", rtas_power_off);
spapr_rtas_register("system-reboot", rtas_system_reboot);
spapr_rtas_register("query-cpu-stopped-state",
spapr_rtas_register(RTAS_DISPLAY_CHARACTER, "display-character",
rtas_display_character);
spapr_rtas_register(RTAS_GET_TIME_OF_DAY, "get-time-of-day",
rtas_get_time_of_day);
spapr_rtas_register(RTAS_SET_TIME_OF_DAY, "set-time-of-day",
rtas_set_time_of_day);
spapr_rtas_register(RTAS_POWER_OFF, "power-off", rtas_power_off);
spapr_rtas_register(RTAS_SYSTEM_REBOOT, "system-reboot",
rtas_system_reboot);
spapr_rtas_register(RTAS_QUERY_CPU_STOPPED_STATE, "query-cpu-stopped-state",
rtas_query_cpu_stopped_state);
spapr_rtas_register("start-cpu", rtas_start_cpu);
spapr_rtas_register("stop-self", rtas_stop_self);
spapr_rtas_register("ibm,get-system-parameter",
spapr_rtas_register(RTAS_START_CPU, "start-cpu", rtas_start_cpu);
spapr_rtas_register(RTAS_STOP_SELF, "stop-self", rtas_stop_self);
spapr_rtas_register(RTAS_IBM_GET_SYSTEM_PARAMETER,
"ibm,get-system-parameter",
rtas_ibm_get_system_parameter);
spapr_rtas_register("ibm,set-system-parameter",
spapr_rtas_register(RTAS_IBM_SET_SYSTEM_PARAMETER,
"ibm,set-system-parameter",
rtas_ibm_set_system_parameter);
}

Expand Down
5 changes: 3 additions & 2 deletions hw/ppc/spapr_vio.c
Expand Up @@ -517,8 +517,9 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
spapr_register_hypercall(H_ENABLE_CRQ, h_enable_crq);

/* RTAS calls */
spapr_rtas_register("ibm,set-tce-bypass", rtas_set_tce_bypass);
spapr_rtas_register("quiesce", rtas_quiesce);
spapr_rtas_register(RTAS_IBM_SET_TCE_BYPASS, "ibm,set-tce-bypass",
rtas_set_tce_bypass);
spapr_rtas_register(RTAS_QUIESCE, "quiesce", rtas_quiesce);

return bus;
}
Expand Down
41 changes: 40 additions & 1 deletion include/hw/ppc/spapr.h
Expand Up @@ -358,6 +358,45 @@ static inline int spapr_allocate_lsi(int hint)
#define RTAS_OUT_NOT_SUPPORTED -3
#define RTAS_OUT_NOT_AUTHORIZED -9002

/* RTAS tokens */
#define RTAS_TOKEN_BASE 0x2000

#define RTAS_DISPLAY_CHARACTER (RTAS_TOKEN_BASE + 0x00)
#define RTAS_GET_TIME_OF_DAY (RTAS_TOKEN_BASE + 0x01)
#define RTAS_SET_TIME_OF_DAY (RTAS_TOKEN_BASE + 0x02)
#define RTAS_POWER_OFF (RTAS_TOKEN_BASE + 0x03)
#define RTAS_SYSTEM_REBOOT (RTAS_TOKEN_BASE + 0x04)
#define RTAS_QUERY_CPU_STOPPED_STATE (RTAS_TOKEN_BASE + 0x05)
#define RTAS_START_CPU (RTAS_TOKEN_BASE + 0x06)
#define RTAS_STOP_SELF (RTAS_TOKEN_BASE + 0x07)
#define RTAS_IBM_GET_SYSTEM_PARAMETER (RTAS_TOKEN_BASE + 0x08)
#define RTAS_IBM_SET_SYSTEM_PARAMETER (RTAS_TOKEN_BASE + 0x09)
#define RTAS_IBM_SET_XIVE (RTAS_TOKEN_BASE + 0x0A)
#define RTAS_IBM_GET_XIVE (RTAS_TOKEN_BASE + 0x0B)
#define RTAS_IBM_INT_OFF (RTAS_TOKEN_BASE + 0x0C)
#define RTAS_IBM_INT_ON (RTAS_TOKEN_BASE + 0x0D)
#define RTAS_CHECK_EXCEPTION (RTAS_TOKEN_BASE + 0x0E)
#define RTAS_EVENT_SCAN (RTAS_TOKEN_BASE + 0x0F)
#define RTAS_IBM_SET_TCE_BYPASS (RTAS_TOKEN_BASE + 0x10)
#define RTAS_QUIESCE (RTAS_TOKEN_BASE + 0x11)
#define RTAS_NVRAM_FETCH (RTAS_TOKEN_BASE + 0x12)
#define RTAS_NVRAM_STORE (RTAS_TOKEN_BASE + 0x13)
#define RTAS_READ_PCI_CONFIG (RTAS_TOKEN_BASE + 0x14)
#define RTAS_WRITE_PCI_CONFIG (RTAS_TOKEN_BASE + 0x15)
#define RTAS_IBM_READ_PCI_CONFIG (RTAS_TOKEN_BASE + 0x16)
#define RTAS_IBM_WRITE_PCI_CONFIG (RTAS_TOKEN_BASE + 0x17)
#define RTAS_IBM_QUERY_INTERRUPT_SOURCE_NUMBER (RTAS_TOKEN_BASE + 0x18)
#define RTAS_IBM_CHANGE_MSI (RTAS_TOKEN_BASE + 0x19)
#define RTAS_SET_INDICATOR (RTAS_TOKEN_BASE + 0x1A)
#define RTAS_SET_POWER_LEVEL (RTAS_TOKEN_BASE + 0x1B)
#define RTAS_GET_POWER_LEVEL (RTAS_TOKEN_BASE + 0x1C)
#define RTAS_GET_SENSOR_STATE (RTAS_TOKEN_BASE + 0x1D)
#define RTAS_IBM_CONFIGURE_CONNECTOR (RTAS_TOKEN_BASE + 0x1E)
#define RTAS_IBM_OS_TERM (RTAS_TOKEN_BASE + 0x1F)
#define RTAS_IBM_EXTENDED_OS_TERM (RTAS_TOKEN_BASE + 0x20)

#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x21)

static inline uint64_t ppc64_phys_to_real(uint64_t addr)
{
return addr & ~0xF000000000000000ULL;
Expand All @@ -377,7 +416,7 @@ typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t token,
uint32_t nargs, target_ulong args,
uint32_t nret, target_ulong rets);
int spapr_rtas_register(const char *name, spapr_rtas_fn fn);
void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn);
target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPREnvironment *spapr,
uint32_t token, uint32_t nargs, target_ulong args,
uint32_t nret, target_ulong rets);
Expand Down

0 comments on commit 3a3b850

Please sign in to comment.