diff options
-rw-r--r-- | hw/ppc/spapr.c | 36 | ||||
-rw-r--r-- | hw/ppc/spapr_hcall.c | 21 | ||||
-rw-r--r-- | include/hw/ppc/spapr.h | 9 | ||||
-rw-r--r-- | trace-events | 4 |
4 files changed, 69 insertions, 1 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 9551c00176..c184732025 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -53,6 +53,7 @@ #include "hw/usb.h" #include "qemu/config-file.h" #include "qemu/error-report.h" +#include "trace.h" #include <libfdt.h> @@ -559,6 +560,41 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base, return fdt; } +int spapr_h_cas_compose_response(target_ulong addr, target_ulong size) +{ + void *fdt, *fdt_skel; + sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 }; + + size -= sizeof(hdr); + + /* Create sceleton */ + fdt_skel = g_malloc0(size); + _FDT((fdt_create(fdt_skel, size))); + _FDT((fdt_begin_node(fdt_skel, ""))); + _FDT((fdt_end_node(fdt_skel))); + _FDT((fdt_finish(fdt_skel))); + fdt = g_malloc0(size); + _FDT((fdt_open_into(fdt_skel, fdt, size))); + g_free(fdt_skel); + + /* Place to make changes to the tree */ + + /* Pack resulting tree */ + _FDT((fdt_pack(fdt))); + + if (fdt_totalsize(fdt) + sizeof(hdr) > size) { + trace_spapr_cas_failed(size); + return -1; + } + + cpu_physical_memory_write(addr, &hdr, sizeof(hdr)); + cpu_physical_memory_write(addr + sizeof(hdr), fdt, fdt_totalsize(fdt)); + trace_spapr_cas_continue(fdt_totalsize(fdt) + sizeof(hdr)); + g_free(fdt); + + return 0; +} + static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt) { uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0), diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index 0bae0535e8..2f6aa5cf79 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -752,6 +752,24 @@ out: return ret; } +static target_ulong h_client_architecture_support(PowerPCCPU *cpu_, + sPAPREnvironment *spapr, + target_ulong opcode, + target_ulong *args) +{ + target_ulong list = args[0]; + + if (!list) { + return H_SUCCESS; + } + + if (spapr_h_cas_compose_response(args[1], args[2])) { + qemu_system_reset_request(); + } + + return H_SUCCESS; +} + static spapr_hcall_fn papr_hypercall_table[(MAX_HCALL_OPCODE / 4) + 1]; static spapr_hcall_fn kvmppc_hypercall_table[KVMPPC_HCALL_MAX - KVMPPC_HCALL_BASE + 1]; @@ -831,6 +849,9 @@ static void hypercall_register_types(void) spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas); spapr_register_hypercall(H_SET_MODE, h_set_mode); + + /* ibm,client-architecture-support support */ + spapr_register_hypercall(KVMPPC_H_CAS, h_client_architecture_support); } type_init(hypercall_register_types) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 9f8bb89600..b8c2ba4a4d 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -303,10 +303,16 @@ typedef struct sPAPREnvironment { #define KVMPPC_HCALL_BASE 0xf000 #define KVMPPC_H_RTAS (KVMPPC_HCALL_BASE + 0x0) #define KVMPPC_H_LOGICAL_MEMOP (KVMPPC_HCALL_BASE + 0x1) -#define KVMPPC_HCALL_MAX KVMPPC_H_LOGICAL_MEMOP +/* Client Architecture support */ +#define KVMPPC_H_CAS (KVMPPC_HCALL_BASE + 0x2) +#define KVMPPC_HCALL_MAX KVMPPC_H_CAS extern sPAPREnvironment *spapr; +typedef struct sPAPRDeviceTreeUpdateHeader { + uint32_t version_id; +} sPAPRDeviceTreeUpdateHeader; + /*#define DEBUG_SPAPR_HCALLS*/ #ifdef DEBUG_SPAPR_HCALLS @@ -402,6 +408,7 @@ struct sPAPRTCETable { void spapr_events_init(sPAPREnvironment *spapr); void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq); +int spapr_h_cas_compose_response(target_ulong addr, target_ulong size); sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, size_t window_size); MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet); diff --git a/trace-events b/trace-events index b35c39b674..9f12843840 100644 --- a/trace-events +++ b/trace-events @@ -1189,6 +1189,10 @@ xics_ics_write_xive(int nr, int srcno, int server, uint8_t priority) "ics_write_ xics_ics_reject(int nr, int srcno) "reject irq %#x [src %d]" xics_ics_eoi(int nr) "ics_eoi: irq %#x" +# hw/ppc/spapr.c +spapr_cas_failed(unsigned long n) "DT diff buffer is too small: %ld bytes" +spapr_cas_continue(unsigned long n) "Copy changes to the guest: %ld bytes" + # hw/ppc/spapr_iommu.c spapr_iommu_put(uint64_t liobn, uint64_t ioba, uint64_t tce, uint64_t ret) "liobn=%"PRIx64" ioba=0x%"PRIx64" tce=0x%"PRIx64" ret=%"PRId64 spapr_iommu_get(uint64_t liobn, uint64_t ioba, uint64_t ret, uint64_t tce) "liobn=%"PRIx64" ioba=0x%"PRIx64" ret=%"PRId64" tce=0x%"PRIx64 |