From 3a3b8502e6f0c8d30865c5f36d2c3ae4114000b5 Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Mon, 23 Jun 2014 23:26:32 +1000 Subject: spapr: Fix RTAS token numbers 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 Signed-off-by: Alexander Graf --- hw/intc/xics.c | 8 +++--- hw/intc/xics_kvm.c | 22 ++++++----------- hw/nvram/spapr_nvram.c | 4 +-- hw/ppc/spapr_events.c | 3 ++- hw/ppc/spapr_pci.c | 18 +++++++++----- hw/ppc/spapr_rtas.c | 67 +++++++++++++++++++++++++------------------------- hw/ppc/spapr_vio.c | 5 ++-- 7 files changed, 64 insertions(+), 63 deletions(-) (limited to 'hw') diff --git a/hw/intc/xics.c b/hw/intc/xics.c index 76dd6f5..493a2a4 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -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); diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index 09476ae..4704c98 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -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; @@ -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; diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c index af49c46..6a72ef4 100644 --- a/hw/nvram/spapr_nvram.c +++ b/hw/nvram/spapr_nvram.c @@ -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; } diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index 16fa49e..5ce96a7 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -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); } diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 988f8cb..8607c88 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -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); } } diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 8d08539..4e87d02 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -36,9 +36,6 @@ #include -#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, @@ -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); @@ -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, @@ -359,7 +352,7 @@ 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) { @@ -367,7 +360,7 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr, } 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)); @@ -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); } diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index 04e16ae..a195fd1 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -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; } -- cgit v1.1