[Qemu-devel] [RFC PATCH v2] tests: rtl8139: test timers and interrupt
Test behaviour of timers and interrupts related to timeouts. Signed-off-by: Frediano Ziglio --- tests/Makefile | 2 +- tests/rtl8139-test.c | 180 +++ 2 files changed, 181 insertions(+), 1 deletion(-) This patch was derived from a test I did while implementing timer in rtl8139 code. Now that there is support for integrated testing I converted it. The test was tested on a real NIC. As if it's the first test I wrote I don't know if syntax and details are fine. For instance should I remove nop test? Should I split my test? Changed from v1: - style diff --git a/tests/Makefile b/tests/Makefile index e4ddb6a..8858407 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -320,7 +320,7 @@ tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y) tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y) tests/e1000-test$(EXESUF): tests/e1000-test.o -tests/rtl8139-test$(EXESUF): tests/rtl8139-test.o +tests/rtl8139-test$(EXESUF): tests/rtl8139-test.o $(libqos-pc-obj-y) tests/pcnet-test$(EXESUF): tests/pcnet-test.o tests/eepro100-test$(EXESUF): tests/eepro100-test.o tests/vmxnet3-test$(EXESUF): tests/vmxnet3-test.o diff --git a/tests/rtl8139-test.c b/tests/rtl8139-test.c index f6a1be3..f0044bb 100644 --- a/tests/rtl8139-test.c +++ b/tests/rtl8139-test.c @@ -10,19 +10,199 @@ #include #include #include "libqtest.h" +#include "libqos/pci-pc.h" #include "qemu/osdep.h" +#include "qemu-common.h" /* Tests only initialization so far. TODO: Replace with functional tests */ static void nop(void) { } +#define CLK 3300 +#define NS_PER_SEC 10ULL + +static QPCIBus *pcibus; +static QPCIDevice *dev; +static void *dev_base; + +static void save_fn(QPCIDevice *dev, int devfn, void *data) +{ +QPCIDevice **pdev = (QPCIDevice **) data; + +*pdev = dev; +} + +static QPCIDevice *get_device(void) +{ +QPCIDevice *dev; + +pcibus = qpci_init_pc(); +qpci_device_foreach(pcibus, 0x10ec, 0x8139, save_fn, &dev); +g_assert(dev != NULL); + +return dev; +} + +#define PORT(name, len, val) \ +static unsigned __attribute__((unused)) in_##name(void) \ +{ \ +unsigned res = qpci_io_read##len(dev, dev_base+(val)); \ +g_test_message("*%s -> %x\n", #name, res); \ +return res; \ +} \ +static void out_##name(unsigned v) \ +{ \ +g_test_message("%x -> *%s\n", v, #name); \ +qpci_io_write##len(dev, dev_base+(val), v); \ +} + +PORT(Timer, l, 0x48) +PORT(IntrMask, w, 0x3c) +PORT(IntrStatus, w, 0x3E) +PORT(TimerInt, l, 0x54) + +#define fatal(...) do { g_test_message(__VA_ARGS__); g_assert(0); } while (0) + +static void test_timer(void) +{ +const unsigned from = 0.95 * CLK; +const unsigned to = 1.6 * CLK; + +out_IntrMask(0); + +in_IntrStatus(); +in_Timer(); +in_Timer(); + +/* Test 1. test counter continue and continue */ +out_TimerInt(0); /* disable timer */ +out_IntrStatus(0x4000); +out_Timer(12345); /* reset timer to 0 */ +unsigned curr = in_Timer(); +unsigned cnt; +if (curr > 0.1 * CLK) { +fatal("time too big %u\n", curr); +} +for (cnt = 0; ; ) { +clock_step(1 * NS_PER_SEC); +unsigned prev = curr; +curr = in_Timer(); + +/* test skip is in a specific range */ +unsigned diff = (curr-prev) & 0xu; +if (diff < from || diff > to) { +fatal("Invalid diff %u (%u-%u)\n", diff, from, to); +} +if (curr < prev && ++cnt == 3) { +break; +} +} + +/* Test 2. Check we didn't get an interrupt with TimerInt == 0 */ +if (in_IntrStatus() & 0x4000) { +fatal("got an interrupt\n"); +} + +/* Test 3. Setting TimerInt to 1 and Timer to 0 get interrupt */ +out_TimerInt(1); +out_Timer(0); +clock_step(40); +if ((in_IntrStatus() & 0x4000) == 0) { +fatal("we should have an interrupt here!\n"); +} + +/* Test 3. Check acknowledge */ +out_IntrStatus(0x4000); +if (in_IntrStatus() & 0x4000) { +fatal("got an interrupt\n"); +} + +/* Test. Status set after Timer reset */ +out_Timer(0); +out_TimerInt(0); +out_IntrStatus(0x4000); +curr = in_Timer(); +out_TimerInt(curr + 0.5 * CLK); +clock_step(1 * NS_PER_SEC); +out_Timer(0); +if ((in_IntrStatus() & 0x4000) == 0) { +fatal("we should have an interrupt here!\n"); +} + +/* Test. Status set after TimerInt reset */ +out_Timer(0); +out_TimerInt(0); +out_IntrStatus(0x4000); +curr = in_Timer(); +out_TimerInt(curr + 0.5 * CLK); +clock_step(1 * NS_PER_SEC); +out_TimerInt(0); +if ((in_IntrStatus() & 0x4000) == 0) { +fatal("we should have an interrupt here!\n"); +} + +/* Test 4. Increment TimerInt we should see an interrupt */ +curr = in_Timer(); +unsigned next = curr + 5.0 * CLK; +out_TimerIn
Re: [Qemu-devel] [PATCH RFC v6 13/20] virtio: allow to fail setting status
On Wed, 7 Jan 2015 21:08:21 +0200 "Michael S. Tsirkin" wrote: > On Wed, Jan 07, 2015 at 05:13:32PM +0100, Cornelia Huck wrote: > > On Tue, 30 Dec 2014 14:25:37 +0200 > > "Michael S. Tsirkin" wrote: > > > > > On Thu, Dec 11, 2014 at 02:25:15PM +0100, Cornelia Huck wrote: > > > > virtio-1 allow setting of the FEATURES_OK status bit to fail if > > > > the negotiated feature bits are inconsistent: let's fail > > > > virtio_set_status() in that case and update virtio-ccw to post an > > > > error to the guest. > > > > > > > > Signed-off-by: Cornelia Huck > > > > > > Right but a separate validate_features call is awkward. > > > How about we defer virtio_set_features until FEATURES_OK, > > > and teach virtio_set_features that it can fail? > > > > Hm. But we would need to keep virtio_set_features() where it is called > > now for legacy devices, as they will never see FEATURES_OK, right? > > So > > we need to make this depending on revisions (or whatever the equivalent > > is for pci/mmio), as we cannot check for VERSION_1. Not sure whether > > this makes the code easier to follow. > > So let's make this a separate callback then. > virtio_legacy_set_features? I'm not sure I like that. We'd need to touch every transport, right?
[Qemu-devel] [RFC PATCH v1 10/13] cpus, spapr: reclaim allocated vCPU objects
From: Gu Zheng Signed-off-by: Gu Zheng Signed-off-by: Bharata B Rao (added spapr bits) --- cpus.c | 44 hw/ppc/spapr.c | 14 - include/qom/cpu.h| 11 ++ include/sysemu/kvm.h | 1 + kvm-all.c| 57 +++- 5 files changed, 125 insertions(+), 2 deletions(-) diff --git a/cpus.c b/cpus.c index 1b5168a..98b7199 100644 --- a/cpus.c +++ b/cpus.c @@ -871,6 +871,24 @@ void async_run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data) qemu_cpu_kick(cpu); } +static void qemu_kvm_destroy_vcpu(CPUState *cpu) +{ +CPU_REMOVE(cpu); + +if (kvm_destroy_vcpu(cpu) < 0) { +fprintf(stderr, "kvm_destroy_vcpu failed.\n"); +exit(1); +} + +object_unparent(OBJECT(cpu)); +} + +static void qemu_tcg_destroy_vcpu(CPUState *cpu) +{ +CPU_REMOVE(cpu); +object_unparent(OBJECT(cpu)); +} + static void flush_queued_work(CPUState *cpu) { struct qemu_work_item *wi; @@ -964,6 +982,11 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) } } qemu_kvm_wait_io_event(cpu); +if (cpu->exit && !cpu_can_run(cpu)) { +qemu_kvm_destroy_vcpu(cpu); +qemu_mutex_unlock(&qemu_global_mutex); +return NULL; +} } return NULL; @@ -1018,6 +1041,7 @@ static void tcg_exec_all(void); static void *qemu_tcg_cpu_thread_fn(void *arg) { CPUState *cpu = arg; +CPUState *remove_cpu = NULL; qemu_tcg_init_cpu_signals(); qemu_thread_get_self(cpu->thread); @@ -1052,6 +1076,16 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) } } qemu_tcg_wait_io_event(); +CPU_FOREACH(cpu) { +if (cpu->exit && !cpu_can_run(cpu)) { +remove_cpu = cpu; +break; +} +} +if (remove_cpu) { +qemu_tcg_destroy_vcpu(remove_cpu); +remove_cpu = NULL; +} } return NULL; @@ -1208,6 +1242,13 @@ void resume_all_vcpus(void) } } +void cpu_remove(CPUState *cpu) +{ +cpu->stop = true; +cpu->exit = true; +qemu_cpu_kick(cpu); +} + /* For temporary buffers for forming a name */ #define VCPU_THREAD_NAME_SIZE 16 @@ -1402,6 +1443,9 @@ static void tcg_exec_all(void) break; } } else if (cpu->stop || cpu->stopped) { +if (cpu->exit) { +next_cpu = CPU_NEXT(cpu); +} break; } } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index ec793b1..44405b2 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1910,7 +1910,19 @@ static void spapr_cpu_hotplug_add(DeviceState *dev, CPUState *cs) static void spapr_cpu_release(DeviceState *dev, void *opaque) { -/* Release vCPU */ +CPUState *cs; +int i; +int id = ppc_get_vcpu_dt_id(POWERPC_CPU(CPU(dev))); + +for (i = id; i < id + smp_threads; i++) { +CPU_FOREACH(cs) { +PowerPCCPU *cpu = POWERPC_CPU(cs); + +if (i == ppc_get_vcpu_dt_id(cpu)) { +cpu_remove(cs); +} +} +} } static void spapr_cpu_hotplug_remove(DeviceState *dev, CPUState *cs) diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 2098f1c..30fd0cd 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -206,6 +206,7 @@ struct kvm_run; * @halted: Nonzero if the CPU is in suspended state. * @stop: Indicates a pending stop request. * @stopped: Indicates the CPU has been artificially stopped. + * @exit: Indicates the CPU has exited due to an unplug operation. * @tcg_exit_req: Set to force TCG to stop executing linked TBs for this * CPU and return to its top level loop. * @singlestep_enabled: Flags for single-stepping. @@ -249,6 +250,7 @@ struct CPUState { bool created; bool stop; bool stopped; +bool exit; volatile sig_atomic_t exit_request; uint32_t interrupt_request; int singlestep_enabled; @@ -305,6 +307,7 @@ struct CPUState { QTAILQ_HEAD(CPUTailQ, CPUState); extern struct CPUTailQ cpus; #define CPU_NEXT(cpu) QTAILQ_NEXT(cpu, node) +#define CPU_REMOVE(cpu) QTAILQ_REMOVE(&cpus, cpu, node) #define CPU_FOREACH(cpu) QTAILQ_FOREACH(cpu, &cpus, node) #define CPU_FOREACH_SAFE(cpu, next_cpu) \ QTAILQ_FOREACH_SAFE(cpu, &cpus, node, next_cpu) @@ -610,6 +613,14 @@ void cpu_exit(CPUState *cpu); void cpu_resume(CPUState *cpu); /** + * cpu_remove: + * @cpu: The CPU to remove. + * + * Requests the CPU to be removed. + */ +void cpu_remove(CPUState *cpu); + +/** * qemu_init_vcpu: * @cpu: The vCPU to initialize. * diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 104cf35..da064c1 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -186,6 +186,7 @@ int kvm_has_gsi_routing(void); int kvm_has_intx_set_mask(void); int kvm_init_vcpu(CPUState *cpu); +i
[Qemu-devel] [RFC PATCH v1 06/13] spapr: CPU hotplug support
Support CPU hotplug via device-add command. Use the exising EPOW event infrastructure to send CPU hotplug notification to the guest. Signed-off-by: Bharata B Rao --- hw/ppc/spapr.c | 205 +++- hw/ppc/spapr_events.c | 8 +- target-ppc/translate_init.c | 6 ++ 3 files changed, 215 insertions(+), 4 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 515d770..a293a59 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -330,6 +330,8 @@ static void add_str(GString *s, const gchar *s1) g_string_append_len(s, s1, strlen(s1) + 1); } +uint32_t cpus_per_socket; + static void *spapr_create_fdt_skel(hwaddr initrd_base, hwaddr initrd_size, hwaddr kernel_size, @@ -350,9 +352,9 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base, unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80}; QemuOpts *opts = qemu_opts_find(qemu_find_opts("smp-opts"), NULL); unsigned sockets = opts ? qemu_opt_get_number(opts, "sockets", 0) : 0; -uint32_t cpus_per_socket = sockets ? (smp_cpus / sockets) : 1; char *buf; +cpus_per_socket = sockets ? (smp_cpus / sockets) : 1; add_str(hypertas, "hcall-pft"); add_str(hypertas, "hcall-term"); add_str(hypertas, "hcall-dabr"); @@ -1744,12 +1746,209 @@ static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) } } +/* TODO: Duplicates code from spapr_create_fdt_skel(), Fix this */ +static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, +int drc_index) +{ +PowerPCCPU *cpu = POWERPC_CPU(cs); +CPUPPCState *env = &cpu->env; +PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); +int index = ppc_get_vcpu_dt_id(cpu); +uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), + 0x, 0x}; +uint32_t tbfreq = kvm_enabled() ? kvmppc_get_tbfreq() : TIMEBASE_FREQ; +uint32_t cpufreq = kvm_enabled() ? kvmppc_get_clockfreq() : 10; +uint32_t page_sizes_prop[64]; +size_t page_sizes_prop_size; +int smpt = ppc_get_compat_smt_threads(cpu); +uint32_t servers_prop[smpt]; +uint32_t gservers_prop[smpt * 2]; +int i; +uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; +uint32_t associativity[] = {cpu_to_be32(0x5), +cpu_to_be32(0x0), +cpu_to_be32(0x0), +cpu_to_be32(0x0), +cpu_to_be32(cs->numa_node), +cpu_to_be32(index)}; + +_FDT((fdt_setprop_cell(fdt, offset, "reg", index))); +_FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu"))); + +_FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR]))); +_FDT((fdt_setprop_cell(fdt, offset, "d-cache-block-size", +env->dcache_line_size))); +_FDT((fdt_setprop_cell(fdt, offset, "d-cache-line-size", +env->dcache_line_size))); +_FDT((fdt_setprop_cell(fdt, offset, "i-cache-block-size", +env->icache_line_size))); +_FDT((fdt_setprop_cell(fdt, offset, "i-cache-line-size", +env->icache_line_size))); + +if (pcc->l1_dcache_size) { +_FDT((fdt_setprop_cell(fdt, offset, "d-cache-size", +pcc->l1_dcache_size))); +} else { +fprintf(stderr, "Warning: Unknown L1 dcache size for cpu\n"); +} +if (pcc->l1_icache_size) { +_FDT((fdt_setprop_cell(fdt, offset, "i-cache-size", +pcc->l1_icache_size))); +} else { +fprintf(stderr, "Warning: Unknown L1 icache size for cpu\n"); +} + +_FDT((fdt_setprop_cell(fdt, offset, "timebase-frequency", tbfreq))); +_FDT((fdt_setprop_cell(fdt, offset, "clock-frequency", cpufreq))); +_FDT((fdt_setprop_cell(fdt, offset, "ibm,slb-size", env->slb_nr))); +_FDT((fdt_setprop_string(fdt, offset, "status", "okay"))); +_FDT((fdt_setprop(fdt, offset, "64-bit", NULL, 0))); + +if (env->spr_cb[SPR_PURR].oea_read) { +_FDT((fdt_setprop(fdt, offset, "ibm,purr", NULL, 0))); +} + +if (env->mmu_model & POWERPC_MMU_1TSEG) { +_FDT((fdt_setprop(fdt, offset, "ibm,processor-segment-sizes", + segs, sizeof(segs; +} + +/* Advertise VMX/VSX (vector extensions) if available + * 0 / no property == no vector extensions + * 1 == VMX / Altivec available + * 2 == VSX available */ +if (env->insns_flags & PPC_ALTIVEC) { +uint32_t vmx = (env->insns_flags2 & PPC2_VSX) ? 2 : 1; + +_FDT((fdt_setprop_cell(fdt, offset, "ibm,vmx", vmx))); +} + +/* Advertise DFP (Decimal Floating Point) if available + * 0 / no property == no DFP + * 1 == DFP available */ +if (env->insns_flags2 & PPC2_DFP) { +_FDT((fdt_setp
[Qemu-devel] [RFC PATCH v1 02/13] spapr: Add DRC dt entries for CPUs
Advertise CPU DR-capability to the guest via device tree. Signed-off-by: Bharata B Rao Signed-off-by: Michael Roth [spapr_drc_reset implementation] --- hw/ppc/spapr.c | 28 1 file changed, 28 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 71e7052..98a32d0 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -807,6 +807,14 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr, spapr_populate_chosen_stdout(fdt, spapr->vio_bus); } +if (spapr->dr_cpu_enabled) { +int offset = fdt_path_offset(fdt, "/cpus"); +ret = spapr_drc_populate_dt(fdt, offset, SPAPR_DR_CONNECTOR_TYPE_CPU); +if (ret < 0) { +fprintf(stderr, "Couldn't set up CPU DR device tree properties\n"); +} +} + _FDT((fdt_pack(fdt))); if (fdt_totalsize(fdt) > FDT_MAX_SIZE) { @@ -1358,6 +1366,16 @@ static SaveVMHandlers savevm_htab_handlers = { .load_state = htab_load, }; +static void spapr_drc_reset(void *opaque) +{ +sPAPRDRConnector *drc = opaque; +DeviceState *d = DEVICE(drc); + +if (d) { +device_reset(d); +} +} + /* pSeries LPAR / sPAPR hardware init */ static void ppc_spapr_init(MachineState *machine) { @@ -1383,6 +1401,7 @@ static void ppc_spapr_init(MachineState *machine) long load_limit, fw_size; bool kernel_le = false; char *filename; +int smt = kvmppc_smt_threads(); msi_supported = true; @@ -1526,6 +1545,15 @@ static void ppc_spapr_init(MachineState *machine) spapr->dr_cpu_enabled = smc->dr_cpu_enabled; spapr->dr_lmb_enabled = smc->dr_lmb_enabled; +if (spapr->dr_cpu_enabled) { +for (i = 0; i < max_cpus/smp_threads; i++) { +sPAPRDRConnector *drc = +spapr_dr_connector_new(OBJECT(machine), + SPAPR_DR_CONNECTOR_TYPE_CPU, i * smt); +qemu_register_reset(spapr_drc_reset, drc); +} +} + /* Set up PCI */ spapr_pci_rtas_init(); -- 2.1.0
[Qemu-devel] [RFC PATCH v1 12/13] spapr: Support ibm, dynamic-reconfiguration-memory
Parse ibm,architecture.vec table obtained from the guest and enable memory node configuration via ibm,dynamic-reconfiguration-memory if guest supports it. This is in preparation to support memory hotplug for sPAPR guests. This changes the way memory node configuration is done. Currently all memory nodes are built upfront. But after this patch, only memory@0 node for RMA is built upfront. Guest kernel boots with just that and rest of the memory nodes (via memory@XXX or ibm,dynamic-reconfiguration-memory) are built when guest does ibm,client-architecture-support call. Note: This patch was tested with an enhancement to SLOF that supports addition of device tree nodes from ibm,client-architecture-support call. TODO: Enforce lmb-size alignment for node memory. Signed-off-by: Bharata B Rao --- hw/ppc/spapr.c | 232 - hw/ppc/spapr_hcall.c | 51 +-- include/hw/ppc/spapr.h | 12 ++- 3 files changed, 246 insertions(+), 49 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 9ff08ff..6964b06 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -631,42 +631,6 @@ 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); - -/* Fix skeleton up */ -_FDT((spapr_fixup_cpu_dt(fdt, spapr))); - -/* 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 void spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start, hwaddr size) { @@ -720,7 +684,6 @@ static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt) } if (!mem_start) { /* ppc_spapr_init() checks for rma_size <= node0_size already */ -spapr_populate_memory_node(fdt, i, 0, spapr->rma_size); mem_start += spapr->rma_size; node_size -= spapr->rma_size; } @@ -741,6 +704,190 @@ static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt) return 0; } +/* + * TODO: Take care of sparsemem configuration ? + */ +static uint64_t numa_node_end(uint32_t nodeid) +{ +uint32_t i = 0; +uint64_t addr = 0; + +do { +addr += numa_info[i].node_mem; +} while (++i <= nodeid); + +return addr; +} + +static uint64_t numa_node_start(uint32_t nodeid) +{ +if (!nodeid) { +return 0; +} else { +return numa_node_end(nodeid - 1); +} +} + +/* + * Given the addr, return the NUMA node to which the address belongs to. + */ +static uint32_t get_numa_node(uint64_t addr) +{ +uint32_t i; + +for (i = 0; i < nb_numa_nodes; i++) { +if ((addr >= numa_node_start(i)) && (addr < numa_node_end(i))) { +return i; +} +} + +/* Unassigned memory goes to node 0 by default */ +return 0; +} + +/* Adds ibm,dynamic-reconfiguration-memory node */ +static int spapr_populate_drconf_memory(sPAPREnvironment *spapr, void *fdt) +{ +int root_offset, ret, i, offset; +uint32_t lmb_size = SPAPR_MIN_MEMORY_BLOCK_SIZE; +uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)}; +uint32_t dynamic_memory[DR_LMB_LIST_ENTRY_SIZE]; +uint32_t nr_rma_lmbs = spapr->rma_size/lmb_size; +uint32_t nr_lmbs = spapr->maxram_limit/lmb_size - nr_rma_lmbs; +uint32_t nr_assigned_lmbs = spapr->ram_limit/lmb_size - nr_rma_lmbs; +uint32_t *int_buf, *cur_index, buf_len; + +/* Allocate enough buffer size to fit in ibm,dynamic-memory */ +buf_len = nr_lmbs * DR_LMB_LIST_ENTRY_SIZE * sizeof(uint32_t) + +sizeof(uint32_t); +cur_index = int_buf = g_malloc0(buf_len); +root_offset = fdt_path_offset(fdt, "/"); + + +offset = fdt_add_subnode(fdt, root_offset, + "ibm,dynamic-reconfiguration-memory"); + +ret = fdt_setprop(fdt, offset, "ibm,lmb-size", prop_lmb_size, +sizeof(prop_lmb_size)); +if (ret < 0) { +goto out; +} + +ret = fdt_setprop_cell(fdt, offset, "ibm,memory-flags-mask", +cpu_to_be32(0xff)); +if (ret < 0) { +goto out; +} + +ret = fdt_setprop_cell(fdt, offset, "ibm,memory-preservation-t
[Qemu-devel] [RFC PATCH v1 09/13] spapr: CPU hot unplug support
Support hot removal of CPU for sPAPR guests. Signed-off-by: Bharata B Rao --- hw/ppc/spapr.c | 43 +++ 1 file changed, 43 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 4347471..ec793b1 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1908,6 +1908,22 @@ static void spapr_cpu_hotplug_add(DeviceState *dev, CPUState *cs) drck->attach(drc, dev, fdt, offset, false); } +static void spapr_cpu_release(DeviceState *dev, void *opaque) +{ +/* Release vCPU */ +} + +static void spapr_cpu_hotplug_remove(DeviceState *dev, CPUState *cs) +{ +PowerPCCPU *cpu = POWERPC_CPU(cs); +int id = ppc_get_vcpu_dt_id(cpu); +sPAPRDRConnector *drc = +spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, id); +sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + +drck->detach(drc, dev, spapr_cpu_release, NULL); +} + static void spapr_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -1948,6 +1964,21 @@ static void spapr_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev, return; } +static void spapr_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, +Error **errp) +{ +Error *local_err = NULL; +CPUState *cs = CPU(dev); +PowerPCCPU *cpu = POWERPC_CPU(cs); +sPAPRDRConnector *drc = +spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, cpu->cpu_dt_id); + +spapr_cpu_hotplug_remove(dev, cs); +spapr_hotplug_req_remove_event(drc); +error_propagate(errp, local_err); +return; +} + static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -1958,6 +1989,16 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, } } +static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ +if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { +if (dev->hotplugged) { +spapr_cpu_unplug(hotplug_dev, dev, errp); +} +} +} + static HotplugHandler *spapr_get_hotpug_handler(MachineState *machine, DeviceState *dev) { @@ -1986,6 +2027,8 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) mc->get_hotplug_handler = spapr_get_hotpug_handler; hc->plug = spapr_machine_device_plug; +hc->unplug = spapr_machine_device_unplug; + smc->dr_phb_enabled = false; smc->dr_cpu_enabled = false; smc->dr_lmb_enabled = false; -- 2.1.0
[Qemu-devel] [RFC PATCH v1 05/13] spapr: Support ibm, lrdr-capacity device tree property
Add support for ibm,lrdr-capacity since this is needed by the guest kernel to know about the possible hot-pluggable CPUs and Memory. Define minimum hotpluggable memory size as 256MB and start storing maximum possible memory for the guest in sPAPREnvironment. Signed-off-by: Bharata B Rao --- hw/ppc/spapr.c | 3 ++- hw/ppc/spapr_rtas.c| 28 ++-- include/hw/ppc/spapr.h | 6 -- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index f49b0fa..515d770 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -775,7 +775,7 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr, } /* RTAS */ -ret = spapr_rtas_device_tree_setup(fdt, rtas_addr, rtas_size); +ret = spapr_rtas_device_tree_setup(spapr, fdt, rtas_addr, rtas_size); if (ret < 0) { fprintf(stderr, "Couldn't set up RTAS device tree properties\n"); } @@ -1473,6 +1473,7 @@ static void ppc_spapr_init(MachineState *machine) /* allocate RAM */ spapr->ram_limit = ram_size; +spapr->maxram_limit = machine->maxram_size; memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram", spapr->ram_limit); memory_region_add_subregion(sysmem, 0, ram); diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index d847f45..e8a0f21 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -29,6 +29,7 @@ #include "sysemu/char.h" #include "hw/qdev.h" #include "sysemu/device_tree.h" +#include "sysemu/cpus.h" #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" @@ -551,11 +552,12 @@ void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn) rtas_table[token].fn = fn; } -int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr, - hwaddr rtas_size) +int spapr_rtas_device_tree_setup(sPAPREnvironment *spapr, void *fdt, + hwaddr rtas_addr, hwaddr rtas_size) { int ret; int i; +uint32_t lrdr_capacity[5]; ret = fdt_add_mem_rsv(fdt, rtas_addr, rtas_size); if (ret < 0) { @@ -604,6 +606,28 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr, } } + +ret = qemu_fdt_setprop_cell(fdt, "/rtas", "#address-cells", 0x2); +if (ret < 0) { +fprintf(stderr, "Couldn't add #address-cells rtas property\n"); +} + +ret = qemu_fdt_setprop_cell(fdt, "/rtas", "#size-cells", 0x2); +if (ret < 0) { +fprintf(stderr, "Couldn't add #size-cells rtas property\n"); +} + +lrdr_capacity[0] = cpu_to_be32(spapr->maxram_limit >> 32); +lrdr_capacity[1] = cpu_to_be32(spapr->maxram_limit & 0x); +lrdr_capacity[2] = 0; +lrdr_capacity[3] = cpu_to_be32(SPAPR_MIN_MEMORY_BLOCK_SIZE); +lrdr_capacity[4] = cpu_to_be32(max_cpus/smp_threads); +ret = qemu_fdt_setprop(fdt, "/rtas", "ibm,lrdr-capacity", lrdr_capacity, + sizeof(lrdr_capacity)); +if (ret < 0) { +fprintf(stderr, "Couldn't add ibm,lrdr-capacity rtas property\n"); +} + return 0; } diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 831db6b..ae8b4e1 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -18,6 +18,7 @@ typedef struct sPAPREnvironment { XICSState *icp; hwaddr ram_limit; +hwaddr maxram_limit; void *htab; uint32_t htab_shift; hwaddr rma_size; @@ -444,8 +445,8 @@ 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); -int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr, - hwaddr rtas_size); +int spapr_rtas_device_tree_setup(sPAPREnvironment *spapr, void *fdt, + hwaddr rtas_addr, hwaddr rtas_size); #define SPAPR_TCE_PAGE_SHIFT 12 #define SPAPR_TCE_PAGE_SIZE(1ULL << SPAPR_TCE_PAGE_SHIFT) @@ -479,6 +480,7 @@ struct sPAPRTCETable { }; #define TIMEBASE_FREQ 51200ULL +#define SPAPR_MIN_MEMORY_BLOCK_SIZE (1 << 28) /* 256MB */ void spapr_events_init(sPAPREnvironment *spapr); void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq); -- 2.1.0
[Qemu-devel] [RFC PATCH v1 07/13] spapr: Start all the threads of CPU core when core is hotplugged
PowerPC kernel adds or removes CPUs in core granularity and hence onlines/offlines all the SMT threads of a core during hot plug/unplug. Support this notion by starting all SMT threads of a core when a core is hotplugged. Signed-off-by: Bharata B Rao --- hw/ppc/spapr.c | 25 + 1 file changed, 25 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index a293a59..4347471 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1376,6 +1376,8 @@ static void spapr_drc_reset(void *opaque) } } +static const char *current_cpu_model; + /* pSeries LPAR / sPAPR hardware init */ static void ppc_spapr_init(MachineState *machine) { @@ -1473,6 +1475,8 @@ static void ppc_spapr_init(MachineState *machine) } } +current_cpu_model = cpu_model; + /* allocate RAM */ spapr->ram_limit = ram_size; spapr->maxram_limit = machine->maxram_size; @@ -1912,10 +1916,31 @@ static void spapr_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev, PowerPCCPU *cpu = POWERPC_CPU(cs); sPAPRDRConnector *drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, cpu->cpu_dt_id); +int id = ppc_get_vcpu_dt_id(cpu); +int smt = kvmppc_smt_threads(); +int i; + +/* + * SMT threads return from here, only main thread (core) will + * continue, create threads and signal hotplug event to the guest. + */ +if ((id % smt) != 0) { +return; +} /* TODO: Check if DR is enabled ? */ g_assert(drc); +/* Start rest of the SMT threads of the hot plugged core */ +for (i = 1; i < smp_threads; i++) { +cpu = cpu_ppc_init(current_cpu_model); +if (cpu == NULL) { +fprintf(stderr, "Unable to find PowerPC CPU definition\n"); +exit(1); +} +spapr_cpu_reset(cpu); +} + spapr_cpu_reset(POWERPC_CPU(CPU(dev))); spapr_cpu_hotplug_add(dev, cs); spapr_hotplug_req_add_event(drc); -- 2.1.0
[Qemu-devel] [RFC PATCH v1 13/13] spapr: Memory hotplug support
Make use of pc-dimm infrastructure to support memory hotplug for PowerPC. Modelled on i386 memory hotplug. Signed-off-by: Bharata B Rao --- hw/ppc/spapr.c| 107 +- hw/ppc/spapr_events.c | 3 ++ 2 files changed, 108 insertions(+), 2 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 6964b06..139 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -58,7 +58,8 @@ #include "hw/nmi.h" #include "hw/compat.h" - +#include "hw/mem/pc-dimm.h" +#include "qapi/qmp/qerror.h" #include /* SLOF memory layout: @@ -2165,6 +2166,103 @@ static void spapr_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, return; } +static int spapr_dimms_capacity(Object *obj, void *opaque) +{ +Error *local_err = NULL; +uint64_t *size = opaque; + +if (object_dynamic_cast(obj, TYPE_PC_DIMM)) { +(*size) += object_property_get_int(obj, PC_DIMM_SIZE_PROP, &local_err); + +if (local_err) { +qerror_report_err(local_err); +error_free(local_err); +return 1; +} +} + +object_child_foreach(obj, spapr_dimms_capacity, opaque); +return 0; +} + +static void spapr_memory_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ +int slot; +Error *local_err = NULL; +sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev); +MachineState *machine = MACHINE(hotplug_dev); +PCDIMMDevice *dimm = PC_DIMM(dev); +PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); +MemoryRegion *mr = ddc->get_memory_region(dimm); +uint64_t dimms_capacity = 0; +uint64_t align = TARGET_PAGE_SIZE; /* TODO: enforce alignment */ +uint64_t addr; +sPAPRDRConnector *drc; + +addr = object_property_get_int(OBJECT(dimm), PC_DIMM_ADDR_PROP, &local_err); +if (local_err) { +goto out; +} + +addr = pc_dimm_get_free_addr(ms->hotplug_memory_base, + memory_region_size(&ms->hotplug_memory), + !addr ? NULL : &addr, align, + memory_region_size(mr), &local_err); +if (local_err) { +goto out; +} + +if (spapr_dimms_capacity(OBJECT(machine), &dimms_capacity)) { +error_setg(&local_err, "failed to get total size of existing DIMMs"); +goto out; +} + +if (dimms_capacity > machine->maxram_size - machine->ram_size) { +error_setg(&local_err, "not enough space, proposed use of 0x%" PRIx64 + " from total of 0x" RAM_ADDR_FMT, + dimms_capacity, machine->maxram_size); +goto out; +} + +object_property_set_int(OBJECT(dev), addr, PC_DIMM_ADDR_PROP, &local_err); +if (local_err) { +goto out; +} + +slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, &local_err); +if (local_err) { +goto out; +} + +slot = pc_dimm_get_free_slot(slot == PC_DIMM_UNASSIGNED_SLOT ? NULL : &slot, + machine->ram_slots, &local_err); +if (local_err) { +goto out; +} +object_property_set_int(OBJECT(dev), slot, PC_DIMM_SLOT_PROP, &local_err); +if (local_err) { +goto out; +} + +if (kvm_enabled() && !kvm_has_free_slot(machine)) { +error_setg(&local_err, "hypervisor has no free memory slots left"); +goto out; +} + +memory_region_add_subregion(&ms->hotplug_memory, +addr - ms->hotplug_memory_base, mr); +vmstate_register_ram(mr, dev); + +drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, +addr/SPAPR_MIN_MEMORY_BLOCK_SIZE); +g_assert(drc); +spapr_hotplug_req_add_event(drc); + +out: +error_propagate(errp, local_err); +} + static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -2172,6 +2270,8 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, if (dev->hotplugged) { spapr_cpu_plug(hotplug_dev, dev, errp); } +} else if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { +spapr_memory_plug(hotplug_dev, dev, errp); } } @@ -2182,13 +2282,16 @@ static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev, if (dev->hotplugged) { spapr_cpu_unplug(hotplug_dev, dev, errp); } +} else if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { +error_setg(errp, "Memory hot unplug is not yet supported\n"); } } static HotplugHandler *spapr_get_hotpug_handler(MachineState *machine, DeviceState *dev) { -if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) { +if (object_dynamic_cast(OBJECT(dev), TYPE_CPU) || +object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { return HOTPLUG_HANDLER(machine); } return NU
[Qemu-devel] [RFC PATCH v1 00/13] CPU and Memory hotplug for PowerPC guests
This patchset enables CPU and memory hotplug support for PowerPC guests. Changes in this patchset (v1): - Based on top of Michael Roth's tree (https://github.com/mdroth/qemu/commits/spapr-hotplug-core) which serves as base for his PCI hotplug patches too. - Switched to device_add/del semantics instead of cpu-add. - Supporting CPU hot unplug now. - Added patches to enable memory hotplug. - Added ibm,dynamic-reconfiguration-memory support which is needed for memory hotplug. v0 - http://lists.nongnu.org/archive/html/qemu-devel/2014-09/msg00752.html CPU hotplug --- - Works with BE guest, has issues with LE guest. Has been tested on BE host only. - Adding a core (and all its threads) in response to device_add command. Similarly removing a core via device_del will remove all the threads. - Using Gu Zheng's "reclaim vCPU objects" patch to remove and reuse the vCPU objects after CPUs removal. (Gu Zheng's original patch: http://lists.gnu.org/archive/html/qemu-devel/2014-12/msg01829.html) Memory hotplug -- - Able to get an LMB added with the current patchset, but there are issues which I am still debugging. - Re-using pc-dimm infrastructure (hw/mem/pc-dimm.c) to support memory hotplug on PowerPC. - Tested with Nathan Fontenot's memory hotplug kernel patches (with additions to drive memory hotplug from EPOW interrupt path) (https://www.marc.info/?l=linuxppc-embedded&m=141626066317143&w=2) Bharata B Rao (11): spapr: Add DRC dt entries for CPUs spapr: Consider max_cpus during xics initialization spapr: Factor out CPU initialization code into realizefn spapr: Support ibm,lrdr-capacity device tree property spapr: CPU hotplug support spapr: Start all the threads of CPU core when core is hotplugged spapr: Enable CPU hotplug for POWER8 CPU family spapr: CPU hot unplug support spapr: Initialize hotplug memory address space spapr: Support ibm,dynamic-reconfiguration-memory spapr: Memory hotplug support Gu Zheng (1): cpus, spapr: reclaim allocated vCPU objects Michael Roth (1): spapr: enable PHB/CPU/LMB hotplug for pseries-2.3 cpus.c| 44 +++ default-configs/ppc64-softmmu.mak | 1 + hw/ppc/spapr.c| 744 ++ hw/ppc/spapr_events.c | 11 +- hw/ppc/spapr_hcall.c | 51 ++- hw/ppc/spapr_rtas.c | 28 +- include/hw/ppc/spapr.h| 27 +- include/qom/cpu.h | 11 + include/sysemu/kvm.h | 1 + kvm-all.c | 57 ++- target-ppc/translate_init.c | 50 ++- 11 files changed, 918 insertions(+), 107 deletions(-) -- 2.1.0
[Qemu-devel] [RFC PATCH v1 04/13] spapr: Factor out CPU initialization code into realizefn
Move some CPU initialization code from machine init function to CPU realizefn so that it can be used from CPU hotplug path too. With the inclusion of ppc.h in translate_init.c, explicit *irq_init() function definitions aren't required, remove them. Signed-off-by: Bharata B Rao --- hw/ppc/spapr.c | 29 + include/hw/ppc/spapr.h | 3 +++ target-ppc/translate_init.c | 43 ++- 3 files changed, 30 insertions(+), 45 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 779d364..f49b0fa 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -81,8 +81,6 @@ #define MIN_RMA_SLOF128UL -#define TIMEBASE_FREQ 51200ULL - #define MAX_CPUS255 #define PHANDLE_XICP0x @@ -971,7 +969,7 @@ static void ppc_spapr_reset(void) } -static void spapr_cpu_reset(void *opaque) +void spapr_cpu_reset(void *opaque) { PowerPCCPU *cpu = opaque; CPUState *cs = CPU(cpu); @@ -1387,7 +1385,6 @@ static void ppc_spapr_init(MachineState *machine) const char *initrd_filename = machine->initrd_filename; const char *boot_device = machine->boot_order; PowerPCCPU *cpu; -CPUPPCState *env; PCIHostState *phb; int i; MemoryRegion *sysmem = get_system_memory(); @@ -1472,30 +1469,6 @@ static void ppc_spapr_init(MachineState *machine) fprintf(stderr, "Unable to find PowerPC CPU definition\n"); exit(1); } -env = &cpu->env; - -/* Set time-base frequency to 512 MHz */ -cpu_ppc_tb_init(env, TIMEBASE_FREQ); - -/* PAPR always has exception vectors in RAM not ROM. To ensure this, - * MSR[IP] should never be set. - */ -env->msr_mask &= ~(1 << 6); - -/* Tell KVM that we're in PAPR mode */ -if (kvm_enabled()) { -kvmppc_set_papr(cpu); -} - -if (cpu->max_compat) { -if (ppc_set_compat(cpu, cpu->max_compat) < 0) { -exit(1); -} -} - -xics_cpu_setup(spapr->icp, cpu); - -qemu_register_reset(spapr_cpu_reset, cpu); } /* allocate RAM */ diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index b1a0838..831db6b 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -478,6 +478,8 @@ struct sPAPRTCETable { QLIST_ENTRY(sPAPRTCETable) list; }; +#define TIMEBASE_FREQ 51200ULL + 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); @@ -494,5 +496,6 @@ int spapr_tcet_dma_dt(void *fdt, int node_off, const char *propname, sPAPRTCETable *tcet); void spapr_hotplug_req_add_event(sPAPRDRConnector *drc); void spapr_hotplug_req_remove_event(sPAPRDRConnector *drc); +void spapr_cpu_reset(void *opaque); #endif /* !defined (__HW_SPAPR_H__) */ diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 72cc9d0..9c642a5 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -30,29 +30,14 @@ #include "qemu/error-report.h" #include "qapi/visitor.h" #include "hw/qdev-properties.h" +#include "hw/ppc/spapr.h" +#include "hw/ppc/ppc.h" //#define PPC_DUMP_CPU //#define PPC_DEBUG_SPR //#define PPC_DUMP_SPR_ACCESSES /* #define USE_APPLE_GDB */ -/* For user-mode emulation, we don't emulate any IRQ controller */ -#if defined(CONFIG_USER_ONLY) -#define PPC_IRQ_INIT_FN(name) \ -static inline void glue(glue(ppc, name),_irq_init) (CPUPPCState *env) \ -{ \ -} -#else -#define PPC_IRQ_INIT_FN(name) \ -void glue(glue(ppc, name),_irq_init) (CPUPPCState *env); -#endif - -PPC_IRQ_INIT_FN(40x); -PPC_IRQ_INIT_FN(6xx); -PPC_IRQ_INIT_FN(970); -PPC_IRQ_INIT_FN(POWER7); -PPC_IRQ_INIT_FN(e500); - /* Generic callbacks: * do nothing but store/retrieve spr value */ @@ -8905,6 +8890,7 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp) CPUState *cs = CPU(dev); PowerPCCPU *cpu = POWERPC_CPU(dev); PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); +CPUPPCState *env = &cpu->env; Error *local_err = NULL; #if !defined(CONFIG_USER_ONLY) int max_smt = kvm_enabled() ? kvmppc_smt_threads() : 1; @@ -8965,6 +8951,29 @@ static void ppc_cpu_realizefn(DeviceState *dev, Error **errp) qemu_init_vcpu(cs); +/* Set time-base frequency to 512 MHz */ +cpu_ppc_tb_init(env, TIMEBASE_FREQ); + +/* PAPR always has exception vectors in RAM not ROM. To ensure this, + * MSR[IP] should never be set. + */ +env->msr_mask &= ~(1 << 6); + +/* Tell KVM that we're in PAPR mode */ +if (kvm_enabled()) { +kvmppc_set_papr(cpu); +
[Qemu-devel] [RFC PATCH v1 01/13] spapr: enable PHB/CPU/LMB hotplug for pseries-2.3
From: Michael Roth Introduce an sPAPRMachineClass sub-class of MachineClass to handle sPAPR-specific machine configuration properties. The 'dr_phb[cpu,lmb]_enabled' field of that class can be set as part of machine-specific init code, and is then propagated to sPAPREnvironment to conditional enable creation of DRC objects and device-tree description to facilitate hotplug of PHBs/CPUs/LMBs. Since we can't migrate this state to older machine types, default the option to false and only enable it for new machine types. Signed-off-by: Michael Roth Signed-off-by: Bharata B Rao [Added CPU and LMB bits] --- hw/ppc/spapr.c | 32 include/hw/ppc/spapr.h | 3 +++ 2 files changed, 35 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 9eb0a94..71e7052 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -89,11 +89,29 @@ #define HTAB_SIZE(spapr)(1ULL << ((spapr)->htab_shift)) +typedef struct sPAPRMachineClass sPAPRMachineClass; typedef struct sPAPRMachineState sPAPRMachineState; #define TYPE_SPAPR_MACHINE "spapr-machine" #define SPAPR_MACHINE(obj) \ OBJECT_CHECK(sPAPRMachineState, (obj), TYPE_SPAPR_MACHINE) +#define SPAPR_MACHINE_GET_CLASS(obj) \ +OBJECT_GET_CLASS(sPAPRMachineClass, obj, TYPE_SPAPR_MACHINE) +#define SPAPR_MACHINE_CLASS(klass) \ +OBJECT_CLASS_CHECK(sPAPRMachineClass, klass, TYPE_SPAPR_MACHINE) + +/** + * sPAPRMachineClass: + */ +struct sPAPRMachineClass { +/*< private >*/ +MachineClass parent_class; + +/*< public >*/ +bool dr_phb_enabled; /* enable dynamic-reconfig/hotplug of PHBs */ +bool dr_cpu_enabled; /* enable dynamic-reconfig/hotplug of CPUs */ +bool dr_lmb_enabled; /* enable dynamic-reconfig/hotplug of LMBs */ +}; /** * sPAPRMachineState: @@ -1343,6 +1361,7 @@ static SaveVMHandlers savevm_htab_handlers = { /* pSeries LPAR / sPAPR hardware init */ static void ppc_spapr_init(MachineState *machine) { +sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(machine); ram_addr_t ram_size = machine->ram_size; const char *cpu_model = machine->cpu_model; const char *kernel_filename = machine->kernel_filename; @@ -1503,6 +1522,10 @@ static void ppc_spapr_init(MachineState *machine) /* We always have at least the nvram device on VIO */ spapr_create_nvram(spapr); +spapr->dr_phb_enabled = smc->dr_phb_enabled; +spapr->dr_cpu_enabled = smc->dr_cpu_enabled; +spapr->dr_lmb_enabled = smc->dr_lmb_enabled; + /* Set up PCI */ spapr_pci_rtas_init(); @@ -1722,6 +1745,7 @@ static void spapr_nmi(NMIState *n, int cpu_index, Error **errp) static void spapr_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); +sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); FWPathProviderClass *fwc = FW_PATH_PROVIDER_CLASS(oc); NMIClass *nc = NMI_CLASS(oc); @@ -1733,6 +1757,9 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) mc->default_boot_order = NULL; mc->kvm_type = spapr_kvm_type; mc->has_dynamic_sysbus = true; +smc->dr_phb_enabled = false; +smc->dr_cpu_enabled = false; +smc->dr_lmb_enabled = false; fwc->get_dev_path = spapr_get_fw_dev_path; nc->nmi_monitor_handler = spapr_nmi; @@ -1744,6 +1771,7 @@ static const TypeInfo spapr_machine_info = { .abstract = true, .instance_size = sizeof(sPAPRMachineState), .instance_init = spapr_machine_initfn, +.class_size= sizeof(sPAPRMachineClass), .class_init= spapr_machine_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_FW_PATH_PROVIDER }, @@ -1788,11 +1816,15 @@ static const TypeInfo spapr_machine_2_2_info = { static void spapr_machine_2_3_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); +sPAPRMachineClass *smc = SPAPR_MACHINE_CLASS(oc); mc->name = "pseries-2.3"; mc->desc = "pSeries Logical Partition (PAPR compliant) v2.3"; mc->alias = "pseries"; mc->is_default = 1; +smc->dr_phb_enabled = true; +smc->dr_cpu_enabled = true; +smc->dr_lmb_enabled = true; } static const TypeInfo spapr_machine_2_3_info = { diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 973193d..b1a0838 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -30,6 +30,9 @@ typedef struct sPAPREnvironment { uint64_t rtc_offset; struct PPCTimebase tb; bool has_graphics; +bool dr_phb_enabled; /* hotplug / dynamic-reconfiguration of PHBs */ +bool dr_cpu_enabled; /* hotplug / dynamic-reconfiguration of CPUs */ +bool dr_lmb_enabled; /* hotplug / dynamic-reconfiguration of LMBs */ uint32_t check_exception_irq; Notifier epow_notifier; -- 2.1.0
[Qemu-devel] [RFC PATCH v1 11/13] spapr: Initialize hotplug memory address space
Initialize a hotplug memory region under which all the hotplugged memory is accommodated. Also enable memory hotplug by setting CONFIG_MEM_HOTPLUG. Modelled on i386 memory hotplug. Signed-off-by: Bharata B Rao --- default-configs/ppc64-softmmu.mak | 1 + hw/ppc/spapr.c| 26 ++ include/hw/ppc/spapr.h| 3 +++ 3 files changed, 30 insertions(+) diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak index bd30d69..03210de 100644 --- a/default-configs/ppc64-softmmu.mak +++ b/default-configs/ppc64-softmmu.mak @@ -60,3 +60,4 @@ CONFIG_I82374=y CONFIG_I8257=y CONFIG_MC146818RTC=y CONFIG_ISA_TESTDEV=y +CONFIG_MEM_HOTPLUG=y diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 44405b2..9ff08ff 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -120,6 +120,8 @@ struct sPAPRMachineState { /*< public >*/ char *kvm_type; +ram_addr_t hotplug_memory_base; +MemoryRegion hotplug_memory; }; sPAPREnvironment *spapr; @@ -1403,6 +1405,7 @@ static void ppc_spapr_init(MachineState *machine) bool kernel_le = false; char *filename; int smt = kvmppc_smt_threads(); +sPAPRMachineState *ms = SPAPR_MACHINE(machine); msi_supported = true; @@ -1492,6 +1495,29 @@ static void ppc_spapr_init(MachineState *machine) memory_region_add_subregion(sysmem, 0, rma_region); } +if (machine->ram_size < machine->maxram_size) { +ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size; + +if (machine->ram_slots > SPAPR_MAX_RAM_SLOTS) { +error_report("unsupported amount of memory slots: %"PRIu64, + machine->ram_slots); +exit(EXIT_FAILURE); +} + +ms->hotplug_memory_base = ROUND_UP(machine->ram_size, 1ULL << 30); + +if ((ms->hotplug_memory_base + hotplug_mem_size) < hotplug_mem_size) { +error_report("unsupported amount of maximum memory: " RAM_ADDR_FMT, + machine->maxram_size); +exit(EXIT_FAILURE); +} + +memory_region_init(&ms->hotplug_memory, OBJECT(ms), + "hotplug-memory", hotplug_mem_size); +memory_region_add_subregion(sysmem, ms->hotplug_memory_base, +&ms->hotplug_memory); +} + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin"); spapr->rtas_size = get_image_size(filename); spapr->rtas_blob = g_malloc(spapr->rtas_size); diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index ae8b4e1..64681c4 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -482,6 +482,9 @@ struct sPAPRTCETable { #define TIMEBASE_FREQ 51200ULL #define SPAPR_MIN_MEMORY_BLOCK_SIZE (1 << 28) /* 256MB */ +/* Support a min of 1TB hotplug memory assuming 256MB per slot */ +#define SPAPR_MAX_RAM_SLOTS (1ULL << 12) + 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); -- 2.1.0
[Qemu-devel] [RFC PATCH v1 03/13] spapr: Consider max_cpus during xics initialization
Use max_cpus instead of smp_cpus when intializating xics system. Also report max_cpus in ibm,interrupt-server-ranges device tree property of interrupt controller node. Signed-off-by: Bharata B Rao --- hw/ppc/spapr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 98a32d0..779d364 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -347,7 +347,7 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base, GString *hypertas = g_string_sized_new(256); GString *qemu_hypertas = g_string_sized_new(256); uint32_t refpoints[] = {cpu_to_be32(0x4), cpu_to_be32(0x4)}; -uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)}; +uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(max_cpus)}; int smt = kvmppc_smt_threads(); unsigned char vec5[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x80}; QemuOpts *opts = qemu_opts_find(qemu_find_opts("smp-opts"), NULL); @@ -1459,7 +1459,7 @@ static void ppc_spapr_init(MachineState *machine) } /* Set up Interrupt Controller before we create the VCPUs */ -spapr->icp = xics_system_init(smp_cpus * kvmppc_smt_threads() / smp_threads, +spapr->icp = xics_system_init(max_cpus * kvmppc_smt_threads() / smp_threads, XICS_IRQS); /* init CPUs */ -- 2.1.0
[Qemu-devel] [RFC PATCH v1 08/13] spapr: Enable CPU hotplug for POWER8 CPU family
Signed-off-by: Bharata B Rao --- target-ppc/translate_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index cf9d8d3..cda706b 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -8184,6 +8184,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data) dc->fw_name = "PowerPC,POWER8"; dc->desc = "POWER8"; dc->props = powerpc_servercpu_properties; +dc->cannot_instantiate_with_device_add_yet = false; pcc->pvr_match = ppc_pvr_match_power8; pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06; pcc->init_proc = init_proc_POWER8; -- 2.1.0
Re: [Qemu-devel] [Makefile] Compiling Qemu to dynamic library
Hi All, During building this so library, I found that there are many functions with same name in stubs and other source file, for example, There are two implement functions with same name slirp_pollfds_fill in slirp.c and main-loop.c. ./stubs/slirp.c:void slirp_pollfds_fill(GArray *pollfds, uint32_t *timeout) ./main-loop.c:slirp_pollfds_fill(gpollfds, &timeout); Do you know when qemustub should be used? libqemustub.a is only used for qemu-img, qemu-nbd, qemu-io, but not for qemu-system-x86_64(and other platform binary)? Thanks! Best Regards Halsey Pian From: Halsey Pian [mailto:halsey.p...@gmail.com] Sent: 2015年1月7日 16:37 To: qemu-devel@nongnu.org Subject: [Qemu-devel] [Makefile] Compiling Qemu to dynamic library Dear All, Recently, I would try to compile qemu to a so in order to call qemu internal functions in my program, I’m trying to do this by steps, 1. Add rules in qemu-2.1.2/ rules.mak %.so: $(call quiet-command,rm -f $@ && $(LINKPROG) $(QEMU_INCLUDES) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) -fPIC -shared -DBUILD_DSO $(CFLAGS) $($@-cflags) $(LDFLAGS) $(LIBS) -o $@ $^," GEN$(TARGET_DIR)$@") 2. Add target in qemu-2.1.2/Makefile qemu-kvm-obj = vl.o blockdev.o migration.o migration-unix.o qtest.o migration-fd.o ioport.o savevm.o cpus.o qemu-kvm-obj += net/net.o net/queue.o qemu-kvm-obj += ui/console.o qemu-kvm-obj += qom/object.o qemu-kvm-obj += hw/usb/bus.o qemu-kvm-obj += pixman/pixman/pixman-bits-image.o pixman/pixman/pixman-utils.o qemu-kvm-obj += qapi/qapi-visit-core.o libqemu.so : $(block-obj-y) $(util-obj-y) qemu-img.o vmstate.o qemu-file.o $(qemu-kvm-obj) vl.o qapi-event.o migration.o blockdev. o migration-unix.o qtest.o migration-fd.o as you know, the main entrance for final binary qemu-system-x86_64 is located in vl.c, I just want it and qemu-img.o to be included in the so library, so it seems that there are many dependent objects above should have to be included, that would be suffering problem to be fixed below during doing this, There are many platform dependent source code i.e. cpus.c memory.c, how to compile them into so for specific platform? Is there some guidance for building qemu to so? could you give help on this? Thanks a lot! Best Regards Halsey Pian
[Qemu-devel] flags variable in DisplaySurface structure
Does anyone know what the flags variable means in the DisplaySurface structure located in console.h? struct DisplaySurface { pixman_format_code_t format; pixman_image_t *image; uint8_t flags; };
[Qemu-devel] Ping [PATCH] Fix irq route entries exceed KVM_MAX_IRQ_ROUTES
Ping Patches here: http://patchwork.ozlabs.org/patch/424738/ Description: In multi-core guest, set irq affinity will eventually lead to guest crash, this is a severe BUG, I do not know why this patch was ignored? Wenshuang Ma
Re: [Qemu-devel] [PATCH v2 0/6] aio: Support epoll by introducing qemu_poll abstraction
On Wed, 01/07 15:08, Stefan Hajnoczi wrote: > On Tue, Dec 16, 2014 at 10:04:38AM +0800, Fam Zheng wrote: > > On Thu, 12/04 11:43, Fam Zheng wrote: > > > v2: Emulate nanoseconds precison of timeout with ppoll and timerfd. > > > Their performance is on par with each other, but both much better than > > > qemu.git: > > > > > > syscall high # of fd low # of fd > > > - > > > qemu.git(ppoll) 4496 > > > ppoll+epoll 85101 > > > timerfd+epoll 87109 > > > > More data points. > > > > Xiaomei tested this series (applied on top of RHEL 7 qemu-kvm-rhev) and > > found > > that: > > > > 0) when # of fds is high, epoll solutions are much better (+30%). > > > > 1) timerfd+epoll is slightly better than ppoll+epoll, but the difference is > > minimal. > > > > 2) original code is 2%~5% faster than the new implementations when # of fds > > is > > low. > > What is "high" and "low"? > > I'd like to understand whether they are extremes that almost no users > will encounter or whether they are plausible in the real world. In the origin story, "low" means barely few fds, say 15; and "high" means what we get after plugging one virtio-serial device, say 70. I wouldn't consider it a extreme case because we assign one ioeventfd for each vq, and # of vq could be times of host cpu core number. In a relatively big system it can go to a few hundreds, easily. > > > This leads to the conclusion that that we'll have a small performance > > degradation if merge this series. I'm thinking about possible optimizations. > > Options in my mind are: > > > > 1) Remove 1ns PR_SET_TIMERSLACK in timerfd+epoll, this doesn't make > > qemu_poll > > faster than the old qemu_poll_ns, but may have other positive effects that > > compensate the cost. > > Sounds like a random hack. What is the reasoning for messing with timer > slack? In a test this doesn't work. The reason is that timer slack affects poll sys calls' timeout, therefore they are correlated. Anyway, I've left this. Fam > > Perhaps it is worth investigating timer slack as an independent issue > though. > > > 2) Use dynamic switch between ppoll and timerfd+epoll. In poll-linux.c, We > > start with pure ppoll, while keeping track of elapsed time in ppoll. And > > periodically, we try "timerfd+epoll" for a few iterations, so that we can > > compare if it is faster than pure ppoll. If it is, swap them, use > > timerfd+epoll > > and and periodically try "ppoll". > > > > That said, I'll also look at the kernel side. Maybe optimizing ppoll or just > > add EPOLL_NANOSECOND_TIMEOUT to epoll_create1 is a better place for > > engineering. > > I agree that a kernel fix would be good. Even if the patch is rejected, > we might get good ideas on how applications can optimize. > > Stefan
Re: [Qemu-devel] [RFC PATCH] tests: rtl8139: test timers and interrupt
On Thu, 01/08 00:07, Frediano Ziglio wrote: > Test behaviour of timers and interrupts related to timeouts. > > Signed-off-by: Frediano Ziglio > --- > tests/Makefile | 2 +- > tests/rtl8139-test.c | 164 > +++ > 2 files changed, 165 insertions(+), 1 deletion(-) > > This patch was derived from a test I did while implementing timer in > rtl8139 code. Now that there is support for integrated testing I converted > it. The test was tested on a real NIC. > > As if it's the first test I wrote I don't know if syntax and details are > fine. For instance should I remove nop test? Should I split my test? > > diff --git a/tests/Makefile b/tests/Makefile > index e4ddb6a..8858407 100644 > --- a/tests/Makefile > +++ b/tests/Makefile > @@ -320,7 +320,7 @@ tests/tmp105-test$(EXESUF): tests/tmp105-test.o > $(libqos-omap-obj-y) > tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) > tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y) > tests/e1000-test$(EXESUF): tests/e1000-test.o > -tests/rtl8139-test$(EXESUF): tests/rtl8139-test.o > +tests/rtl8139-test$(EXESUF): tests/rtl8139-test.o $(libqos-pc-obj-y) > tests/pcnet-test$(EXESUF): tests/pcnet-test.o > tests/eepro100-test$(EXESUF): tests/eepro100-test.o > tests/vmxnet3-test$(EXESUF): tests/vmxnet3-test.o > diff --git a/tests/rtl8139-test.c b/tests/rtl8139-test.c > index f6a1be3..87f1792 100644 > --- a/tests/rtl8139-test.c > +++ b/tests/rtl8139-test.c > @@ -10,19 +10,183 @@ > #include > #include > #include "libqtest.h" > +#include "libqos/pci-pc.h" > #include "qemu/osdep.h" > +#include "qemu-common.h" > > /* Tests only initialization so far. TODO: Replace with functional tests */ > static void nop(void) > { > } > > +#define CLK 3300 > +#define NS_PER_SEC 10ULL > + > +static QPCIBus *pcibus; > +static QPCIDevice *dev = NULL; > +static void *dev_base = NULL; > + > +static void save_fn(QPCIDevice *dev, int devfn, void *data) > +{ > +QPCIDevice **pdev = (QPCIDevice **) data; > + > +*pdev = dev; > +} > + > +static QPCIDevice *get_device(void) > +{ > +QPCIDevice *dev; > + > +pcibus = qpci_init_pc(); > +qpci_device_foreach(pcibus, 0x10ec, 0x8139, save_fn, &dev); > +g_assert(dev != NULL); > + > +return dev; > +} > + > +#define PORT(name,len,val) \ > +static unsigned __attribute__((unused)) in_##name(void) { \ > +unsigned res = qpci_io_read##len(dev,dev_base+(val)); \ > +g_test_message("*%s -> %x\n", #name, res); \ > +return res; \ > +} \ > +static void out_##name(unsigned v) { \ > +g_test_message("%x -> *%s\n", v, #name); \ > +qpci_io_write##len(dev,dev_base+(val),v); \ > +} > + > +PORT(Timer,l,0x48) > +PORT(IntrMask,w,0x3c) > +PORT(IntrStatus,w,0x3E) > +PORT(TimerInt,l,0x54) > + > +#define fatal(...) do { g_test_message(__VA_ARGS__); g_assert(0); } while(0) > + > +static void test_timer(void) > +{ > +const unsigned from = 0.95 * CLK; > +const unsigned to = 1.6 * CLK; > + > +out_IntrMask(0); > + > +in_IntrStatus(); > +in_Timer(); > +in_Timer(); > + > +// Test 1. test counter continue and continue Plesae use /* */ for comments in this patch. There are also other coding style issues, please test it with scripts/checkpatch.pl and fix them in next version. Thanks, Fam > +out_TimerInt(0); // disable timer > +out_IntrStatus(0x4000); > +out_Timer(12345); // reset timer to 0 > +unsigned curr = in_Timer(); > +unsigned cnt; > +if (curr > 0.1 * CLK) > +fatal("time too big %u\n", curr); > +for (cnt=0;;) { > +clock_step(1 * NS_PER_SEC); > +unsigned prev = curr; > +curr = in_Timer(); > + > +// test skip is in a specific range > +unsigned diff = (curr-prev) & 0xu; > +if (diff < from || diff > to) > +fatal("Invalid diff %u (%u-%u)\n", diff, from,to); > +if (curr < prev && ++cnt == 3) > +break; > +} > + > +// Test 2. Check we didn't get an interrupt with TimerInt == 0 > +if (in_IntrStatus() & 0x4000) > +fatal("got an interrupt\n"); > + > +// Test 3. Setting TimerInt to 1 and Timer to 0 get interrupt > +out_TimerInt(1); > +out_Timer(0); > +clock_step(40); > +if ((in_IntrStatus() & 0x4000) == 0) > +fatal("we should have an interrupt here!\n"); > + > +// Test 3. Check acknowledge > +out_IntrStatus(0x4000); > +if (in_IntrStatus() & 0x4000) > +fatal("got an interrupt\n"); > + > +// Test. Status set after Timer reset > +out_Timer(0); > +out_TimerInt(0); > +out_IntrStatus(0x4000); > +curr = in_Timer(); > +out_TimerInt(curr + 0.5 * CLK); > +clock_step(1 * NS_PER_SEC); > +out_Timer(0); > +if ((in_IntrStatus() & 0x4000) == 0) > +fatal("we should have an interrupt here!\n"); > + > +// Test. Status set after TimerInt reset > +out_Timer(0); > +out_TimerInt(0); > +ou
Re: [Qemu-devel] [PATCH v2] target-openrisc: bugfix for dec_sys to decode instructions correctly
Hi David, On Wed, Jan 7, 2015 at 1:06 AM, David Morrison wrote: > Fixed the decoding of "system" instructions (starting with 0x2) > in dec_sys() in translate.c. In particular, the l.trap instruction > is now correctly decoded, which enables for singlestepping and > breakpoints to be set in GDB. > > Signed-off-by: David R. Morrison > --- > target-openrisc/translate.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > Changes since previous version: > * Added 'signed-off-by' line; sorry to forget this before! > > diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c > index 407bd97..d36278f 100644 > --- a/target-openrisc/translate.c > +++ b/target-openrisc/translate.c > @@ -1320,7 +1320,7 @@ static void dec_sys(DisasContext *dc, uint32_t insn) > #ifdef OPENRISC_DISAS > uint32_t K16; > #endif > -op0 = extract32(insn, 16, 8); > +op0 = extract32(insn, 16, 10); Thank you for pointing this. Acked-by: Jia Liu > #ifdef OPENRISC_DISAS > K16 = extract32(insn, 0, 16); > #endif > -- > 2.2.1 > Regards, Jia
Re: [Qemu-devel] [Qemu-stable] 2.1 unexpected stop after exporting blockdev via nbd server
Quoting Stefan Hajnoczi (2015-01-06 05:49:11) > On Mon, Jan 05, 2015 at 05:12:10PM +0400, Andrey Korolyov wrote: > > On Fri, Jan 2, 2015 at 4:04 PM, Stefan Hajnoczi wrote: > > > On Thu, Dec 18, 2014 at 07:38:59PM +0400, Andrey Korolyov wrote: > > >> 2.1-stable is currently crashing with the > > >> > > >> Co-routine re-entered recursively > > >> 2014-12-16 15:06:23.578+: shutting down > > >> > > >> after execution of (for example) following when using virtio-dp as a > > >> disk backend: > > >> > > >> '{ "execute": "nbd-server-start", "arguments": { "addr": { "type": > > >> "inet", "data": { "host": "10.6.0.1", "port": "" } } } }' > > >> '{ "execute": "nbd-server-add", "arguments": {"device": > > >> "drive-virtio-disk0","writable": false } }' > > > > > > Hi, > > > You need patches from Max Reitz that make the run-time NBD server > > > support dataplane: > > > f214928 nbd: Follow the BDS' AIO context > > > 3338442 block: Add AIO context notifiers > > > 958c717 nbd: Drop nbd_can_read() > > > > > > Please try QEMU v2.2.0 or qemu.git. > > > > > > Stefan > > > > Thanks Stefan, those commits are enough to make dataplane drive work > > well with runtime nbd server. By the way, can such functionality > > improvements (not major improvements like discard support for scsi) > > make their way as backports? To reword this, unexpected behavior like > > sudden shutdown I described is better to be closed by later fixes than > > by stubs or left as it currently behaving IMO. > > Oops, I typoed the qemu-sta...@nongnu.org email address. Trying > again... > > QEMU stable folks: will there be another 2.1.x release? Yes, 2.1.3 was very poorly timed to go out before Christmas but obviously that didn't happen. The patch round-up should go out tomorrow with the freeze next Wednesday. The updated schedule is available here: http://qemu-project.org/Planning/2.1#Release_Schedule > > Stefan
[Qemu-devel] [RESEND PATCH v1 12/13] acpi: Add hardware implementation for memory hot unplug.
This patch adds a new bit to memory hotplug IO port indicating that ej0 has been evaluated by guest OS. And call pc-dimm unplug cb to do the real removal. Signed-off-by: Hu Tao Signed-off-by: Tang Chen --- docs/specs/acpi_mem_hotplug.txt | 8 ++-- hw/acpi/memory_hotplug.c| 23 --- hw/core/qdev.c | 2 +- include/hw/qdev-core.h | 1 + 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/docs/specs/acpi_mem_hotplug.txt b/docs/specs/acpi_mem_hotplug.txt index 1290994..28a1ffa 100644 --- a/docs/specs/acpi_mem_hotplug.txt +++ b/docs/specs/acpi_mem_hotplug.txt @@ -19,7 +19,9 @@ Memory hot-plug interface (IO port 0xa00-0xa17, 1-4 byte access): 1: Device insert event, used to distinguish device for which no device check event to OSPM was issued. It's valid only when bit 1 is set. - 2-7: reserved and should be ignored by OSPM + 2: Device remove event, used to indicate that device is being +removed. + 3-7: reserved and should be ignored by OSPM [0x15-0x17] reserved write access: @@ -35,7 +37,9 @@ Memory hot-plug interface (IO port 0xa00-0xa17, 1-4 byte access): 1: if set to 1 clears device insert event, set by OSPM after it has emitted device check event for the selected memory device - 2-7: reserved, OSPM must clear them before writing to register + 2: set by hardware after it has emitted device eject event for +selected memory device + 3-7: reserved, OSPM must clear them before writing to register Selecting memory device slot beyond present range has no effect on platform: - write accesses to memory hot-plug registers not documented above are diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c index 2b0c8ca..b9e8752 100644 --- a/hw/acpi/memory_hotplug.c +++ b/hw/acpi/memory_hotplug.c @@ -2,6 +2,7 @@ #include "hw/acpi/pc-hotplug.h" #include "hw/mem/pc-dimm.h" #include "hw/boards.h" +#include "hw/qdev-core.h" #include "trace.h" #include "qapi-event.h" @@ -75,6 +76,7 @@ static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr, case 0x14: /* pack and return is_* fields */ val |= mdev->is_enabled ? 1 : 0; val |= mdev->is_inserting ? 2 : 0; +val |= mdev->is_removing ? 4 : 0; trace_mhp_acpi_read_flags(mem_st->selector, val); break; default: @@ -90,6 +92,8 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data, MemHotplugState *mem_st = opaque; MemStatus *mdev; ACPIOSTInfo *info; +DeviceState *dev = NULL; +HotplugHandler *hotplug_ctrl = NULL; if (!mem_st->dev_count) { return; @@ -121,21 +125,34 @@ static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data, mdev = &mem_st->devs[mem_st->selector]; mdev->ost_status = data; trace_mhp_acpi_write_ost_status(mem_st->selector, mdev->ost_status); -/* TODO: implement memory removal on guest signal */ info = acpi_memory_device_status(mem_st->selector, mdev); qapi_event_send_acpi_device_ost(info, &error_abort); qapi_free_ACPIOSTInfo(info); break; -case 0x14: +case 0x14: /* set is_* fields */ mdev = &mem_st->devs[mem_st->selector]; + if (data & 2) { /* clear insert event */ mdev->is_inserting = false; trace_mhp_acpi_clear_insert_evt(mem_st->selector); +} else if (data & 4) { /* request removal of device */ +/* + * QEmu memory hot unplug is an asynchronized procedure. QEmu first + * calls pc-dimm unplug request cb to send a SCI to guest. When the + * Guest OS finished handling the SCI, it evaluates ACPI ej0, and + * QEmu calls pc-dimm unplug cb to remove memory device. + */ +dev = DEVICE(mdev->dimm); +hotplug_ctrl = qdev_get_hotplug_handler(dev); +/* Call pc-dimm unplug cb. */ +hotplug_handler_unplug(hotplug_ctrl, dev, NULL); } + +break; +default: break; } - } static const MemoryRegionOps acpi_memory_hotplug_ops = { .read = acpi_memory_hotplug_read, diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 901f289..9f08fe6 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -223,7 +223,7 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, dev->alias_required_for_version = required_for_version; } -static HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev) +HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev) { HotplugHandler *hotplug_ctrl = NULL; diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 589bbe7..60f549e 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/q
[Qemu-devel] [RESEND PATCH v1 13/13] pc, acpi bios: Add memory hot unplug interface.
From: Hu Tao This patch implements MEMORY_SLOT_EJECT_METHOD according to ACPI spec. Signed-off-by: Hu Tao Signed-off-by: Tang Chen --- hw/i386/acpi-dsdt-mem-hotplug.dsl | 11 ++- hw/i386/ssdt-mem.dsl | 5 + include/hw/acpi/pc-hotplug.h | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/hw/i386/acpi-dsdt-mem-hotplug.dsl b/hw/i386/acpi-dsdt-mem-hotplug.dsl index 2a36c47..2a35534 100644 --- a/hw/i386/acpi-dsdt-mem-hotplug.dsl +++ b/hw/i386/acpi-dsdt-mem-hotplug.dsl @@ -50,6 +50,7 @@ Offset(20), MEMORY_SLOT_ENABLED, 1, // 1 if enabled, read only MEMORY_SLOT_INSERT_EVENT, 1, // (read) 1 if has a insert event. (write) 1 to clear event +MEMORY_SLOT_REMOVE_EVENT, 1, // 1 if DIMM has a remove request, read only } Mutex (MEMORY_SLOT_LOCK, 0) @@ -71,8 +72,9 @@ If (LEqual(MEMORY_SLOT_INSERT_EVENT, One)) { // Memory device needs check MEMORY_SLOT_NOTIFY_METHOD(Local0, 1) Store(1, MEMORY_SLOT_INSERT_EVENT) +} Elseif (LEqual(MEMORY_SLOT_REMOVE_EVENT, One)) { // Ejection request +MEMORY_SLOT_NOTIFY_METHOD(Local0, 3) } -// TODO: handle memory eject request Add(Local0, One, Local0) // goto next DIMM } Release(MEMORY_SLOT_LOCK) @@ -172,5 +174,12 @@ Store(Arg2, MEMORY_SLOT_OST_STATUS) Release(MEMORY_SLOT_LOCK) } + +Method(MEMORY_SLOT_EJECT_METHOD, 2) { +Acquire(MEMORY_SLOT_LOCK, 0x) +Store(ToInteger(Arg0), MEMORY_SLOT_SLECTOR) // select DIMM +Store(One, MEMORY_SLOT_REMOVE_EVENT) +Release(MEMORY_SLOT_LOCK) +} } // Device() } // Scope() diff --git a/hw/i386/ssdt-mem.dsl b/hw/i386/ssdt-mem.dsl index 22ff5dd..1416639 100644 --- a/hw/i386/ssdt-mem.dsl +++ b/hw/i386/ssdt-mem.dsl @@ -43,6 +43,7 @@ DefinitionBlock ("ssdt-mem.aml", "SSDT", 0x02, "BXPC", "CSSDT", 0x1) External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_STATUS_METHOD, MethodObj) External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_OST_METHOD, MethodObj) External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_PROXIMITY_METHOD, MethodObj) +External(\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_EJECT_METHOD, MethodObj) Scope(\_SB) { /* v-- DO NOT EDIT --v */ @@ -72,6 +73,10 @@ DefinitionBlock ("ssdt-mem.aml", "SSDT", 0x02, "BXPC", "CSSDT", 0x1) Method(_OST, 3) { \_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_OST_METHOD(_UID, Arg0, Arg1, Arg2) } + +Method(_EJ0, 1) { +\_SB.PCI0.MEMORY_HOTPLUG_DEVICE.MEMORY_SLOT_EJECT_METHOD(_UID, Arg0) +} } } } diff --git a/include/hw/acpi/pc-hotplug.h b/include/hw/acpi/pc-hotplug.h index b9db295..b61b6ea 100644 --- a/include/hw/acpi/pc-hotplug.h +++ b/include/hw/acpi/pc-hotplug.h @@ -42,6 +42,7 @@ #define MEMORY_SLOT_PROXIMITYMPX #define MEMORY_SLOT_ENABLED MES #define MEMORY_SLOT_INSERT_EVENT MINS +#define MEMORY_SLOT_REMOVE_EVENT MRMV #define MEMORY_SLOT_SLECTOR MSEL #define MEMORY_SLOT_OST_EVENTMOEV #define MEMORY_SLOT_OST_STATUS MOSC @@ -50,6 +51,7 @@ #define MEMORY_SLOT_CRS_METHOD MCRS #define MEMORY_SLOT_OST_METHOD MOST #define MEMORY_SLOT_PROXIMITY_METHOD MPXM +#define MEMORY_SLOT_EJECT_METHOD MEJ0 #define MEMORY_SLOT_NOTIFY_METHODMTFY #define MEMORY_SLOT_SCAN_METHOD MSCN -- 1.8.4.2
[Qemu-devel] [RESEND PATCH v1 09/13] acpi, piix4: Add memory hot unplug support for piix4.
Call memory unplug cb in piix4_device_unplug_cb(). --- hw/acpi/piix4.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index f809c3a..4ae4867 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -377,8 +377,16 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev, static void piix4_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { -error_setg(errp, "acpi: device unplug for not supported device" - " type: %s", object_get_typename(OBJECT(dev))); +PIIX4PMState *s = PIIX4_PM(hotplug_dev); + +if (s->acpi_memory_hotplug.is_enabled && +object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { +acpi_memory_unplug_cb(&s->ar, s->irq, &s->acpi_memory_hotplug, + dev, errp); +} else { +error_setg(errp, "acpi: device unplug for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); +} } static void piix4_update_bus_hotplug(PCIBus *pci_bus, void *opaque) -- 1.8.4.2
[Qemu-devel] [RESEND PATCH v1 08/13] acpi, mem-hotplug: Add unplug cb for memory device.
Reset all memory status, and unparent the memory device. --- hw/acpi/memory_hotplug.c | 16 include/hw/acpi/memory_hotplug.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c index 3d8e398..2b0c8ca 100644 --- a/hw/acpi/memory_hotplug.c +++ b/hw/acpi/memory_hotplug.c @@ -227,6 +227,22 @@ void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq, acpi_memory_hotplug_sci(ar, irq); } +void acpi_memory_unplug_cb(ACPIREGS *ar, qemu_irq irq, + MemHotplugState *mem_st, + DeviceState *dev, Error **errp) +{ +MemStatus *mdev; + +mdev = acpi_memory_get_slot_status_descriptor(mem_st, dev, errp); +if (!mdev) +return; + +mdev->is_removing = false; +mdev->is_enabled = false; +object_unparent(OBJECT(mdev->dimm)); +mdev->dimm = NULL; +} + static const VMStateDescription vmstate_memhp_sts = { .name = "memory hotplug device state", .version_id = 1, diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h index c437a85..6b8d9f7 100644 --- a/include/hw/acpi/memory_hotplug.h +++ b/include/hw/acpi/memory_hotplug.h @@ -32,6 +32,8 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, DeviceState *dev, Error **errp); +void acpi_memory_unplug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, + DeviceState *dev, Error **errp); extern const VMStateDescription vmstate_memory_hotplug; #define VMSTATE_MEMORY_HOTPLUG(memhp, state) \ -- 1.8.4.2
[Qemu-devel] [RESEND PATCH v1 10/13] acpi, ich9: Add memory hot unplug support for ich9.
Call memory unplug cb in ich9_pm_device_unplug_cb(). --- hw/acpi/ich9.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index 841f57d..0a8e757 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -317,8 +317,14 @@ void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev, void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp) { -error_setg(errp, "acpi: device unplug for not supported device" - " type: %s", object_get_typename(OBJECT(dev))); +if (pm->acpi_memory_hotplug.is_enabled && +object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { +acpi_memory_unplug_cb(&pm->acpi_regs, pm->irq, + &pm->acpi_memory_hotplug, dev, errp); +} else { +error_setg(errp, "acpi: device unplug for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); +} } void ich9_pm_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list) -- 1.8.4.2
[Qemu-devel] [RESEND PATCH v1 11/13] pc-dimm: Add memory hot unplug support for pc-dimm.
Implement unplug cb for pc-dimm. It remove the corresponding memory region, and unregister vmstat. At last, it calls memory unplug cb to reset memory status and do unparenting. --- hw/i386/pc.c | 25 +++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index f501f1f..3732f67 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1691,6 +1691,23 @@ out: error_propagate(errp, local_err); } +static void pc_dimm_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ +PCMachineState *pcms = PC_MACHINE(hotplug_dev); +PCDIMMDevice *dimm = PC_DIMM(dev); +PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm); +MemoryRegion *mr = ddc->get_memory_region(dimm); +HotplugHandlerClass *hhc; +Error *local_err = NULL; + +memory_region_del_subregion(&pcms->hotplug_memory, mr); +vmstate_unregister_ram(mr, dev); + +hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev); +hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err); +} + static void pc_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -1744,8 +1761,12 @@ static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { -error_setg(errp, "acpi: device unplug for not supported device" - " type: %s", object_get_typename(OBJECT(dev))); +if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { +pc_dimm_unplug(hotplug_dev, dev, errp); +} else { +error_setg(errp, "acpi: device unplug for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); +} } static HotplugHandler *pc_get_hotpug_handler(MachineState *machine, -- 1.8.4.2
[Qemu-devel] [RESEND PATCH v1 07/13] pc-dimm: Add memory hot unplug request support for pc-dimm.
Implement memory unplug request cb for pc-dimm, and call it in pc_machine_device_unplug_request_cb(). --- hw/i386/pc.c | 28 ++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 0f3b1e0..f501f1f 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1671,6 +1671,26 @@ out: error_propagate(errp, local_err); } +static void pc_dimm_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ +HotplugHandlerClass *hhc; +Error *local_err = NULL; +PCMachineState *pcms = PC_MACHINE(hotplug_dev); + +if (!pcms->acpi_dev) { +error_setg(&local_err, + "memory hotplug is not enabled: missing acpi device"); + goto out; +} + +hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev); +hhc->unplug_request(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err); + +out: +error_propagate(errp, local_err); +} + static void pc_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -1713,8 +1733,12 @@ static void pc_machine_device_plug_cb(HotplugHandler *hotplug_dev, static void pc_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { -error_setg(errp, "acpi: device unplug request for not supported device" - " type: %s", object_get_typename(OBJECT(dev))); +if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { +pc_dimm_unplug_request(hotplug_dev, dev, errp); +} else { +error_setg(errp, "acpi: device unplug request for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); +} } static void pc_machine_device_unplug_cb(HotplugHandler *hotplug_dev, -- 1.8.4.2
[Qemu-devel] [RESEND PATCH v1 05/13] acpi, piix4: Add memory hot unplug request support for piix4.
From: Hu Tao Call memory unplug request cb in piix4_device_unplug_request_cb(). Signed-off-by: Hu Tao Signed-off-by: Tang Chen --- hw/acpi/piix4.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 4407388..f809c3a 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -361,7 +361,11 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev, { PIIX4PMState *s = PIIX4_PM(hotplug_dev); -if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { +if (s->acpi_memory_hotplug.is_enabled && +object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { +acpi_memory_unplug_request_cb(&s->ar, s->irq, &s->acpi_memory_hotplug, + dev, errp); +} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { acpi_pcihp_device_unplug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev, errp); } else { -- 1.8.4.2
[Qemu-devel] [RESEND PATCH v1 03/13] acpi, mem-hotplug: Add acpi_memory_hotplug_sci() to rise sci for memory hotplug.
Add a new API named acpi_memory_hotplug_sci() to send memory hotplug SCI. Doing this is because this procedure will be used by other functions in the next coming patches. Signed-off-by: Tang Chen --- hw/acpi/memory_hotplug.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c index ef56bf6..9839963 100644 --- a/hw/acpi/memory_hotplug.c +++ b/hw/acpi/memory_hotplug.c @@ -188,6 +188,12 @@ acpi_memory_get_slot_status_descriptor(MemHotplugState *mem_st, return &mem_st->devs[slot]; } +static void acpi_memory_hotplug_sci(ACPIREGS *ar, qemu_irq irq) +{ +ar->gpe.sts[0] |= ACPI_MEMORY_HOTPLUG_STATUS; +acpi_update_sci(ar, irq); +} + void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, DeviceState *dev, Error **errp) { @@ -201,10 +207,8 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, mdev->is_enabled = true; mdev->is_inserting = true; -/* do ACPI magic */ -ar->gpe.sts[0] |= ACPI_MEMORY_HOTPLUG_STATUS; -acpi_update_sci(ar, irq); -return; +/* Do ACPI magic */ +acpi_memory_hotplug_sci(ar, irq); } static const VMStateDescription vmstate_memhp_sts = { -- 1.8.4.2
[Qemu-devel] [RESEND PATCH v1 04/13] acpi, mem-hotplug: Add unplug request cb for memory device.
Memory hot unplug are both asynchronize procedures. When the unplug operation happens, unplug request cb is called first. And when ghest OS finished handling unplug, unplug cb will be called to do the real removal of device. This patch adds unplug request cb for memory device. Add a new bool member named is_removing to MemStatus indicating that the memory slot is being removed. Set it to true in acpi_memory_unplug_request_cb(), and send SCI to guest. Signed-off-by: Tang Chen --- hw/acpi/memory_hotplug.c | 16 include/hw/acpi/memory_hotplug.h | 4 2 files changed, 20 insertions(+) diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c index 9839963..3d8e398 100644 --- a/hw/acpi/memory_hotplug.c +++ b/hw/acpi/memory_hotplug.c @@ -211,6 +211,22 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, acpi_memory_hotplug_sci(ar, irq); } +void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq, + MemHotplugState *mem_st, + DeviceState *dev, Error **errp) +{ +MemStatus *mdev; + +mdev = acpi_memory_get_slot_status_descriptor(mem_st, dev, errp); +if (!mdev) +return; + +mdev->is_removing = true; + +/* Do ACPI magic */ +acpi_memory_hotplug_sci(ar, irq); +} + static const VMStateDescription vmstate_memhp_sts = { .name = "memory hotplug device state", .version_id = 1, diff --git a/include/hw/acpi/memory_hotplug.h b/include/hw/acpi/memory_hotplug.h index 7bbf8a0..c437a85 100644 --- a/include/hw/acpi/memory_hotplug.h +++ b/include/hw/acpi/memory_hotplug.h @@ -11,6 +11,7 @@ typedef struct MemStatus { DeviceState *dimm; bool is_enabled; bool is_inserting; +bool is_removing; uint32_t ost_event; uint32_t ost_status; } MemStatus; @@ -28,6 +29,9 @@ void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, DeviceState *dev, Error **errp); +void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq, + MemHotplugState *mem_st, + DeviceState *dev, Error **errp); extern const VMStateDescription vmstate_memory_hotplug; #define VMSTATE_MEMORY_HOTPLUG(memhp, state) \ -- 1.8.4.2
[Qemu-devel] [RESEND PATCH v1 02/13] acpi, mem-hotplug: Add acpi_memory_get_slot_status_descriptor() to get MemStatus.
Add a new API named acpi_memory_get_slot_status_descriptor() to obtain a single memory slot status. Doing this is because this procedure will be used by other functions in the next coming patches. Signed-off-by: Tang Chen --- hw/acpi/memory_hotplug.c | 27 +++ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c index c6580da..ef56bf6 100644 --- a/hw/acpi/memory_hotplug.c +++ b/hw/acpi/memory_hotplug.c @@ -163,29 +163,40 @@ void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner, memory_region_add_subregion(as, ACPI_MEMORY_HOTPLUG_BASE, &state->io); } -void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, - DeviceState *dev, Error **errp) +static MemStatus * +acpi_memory_get_slot_status_descriptor(MemHotplugState *mem_st, + DeviceState *dev, Error **errp) { -MemStatus *mdev; Error *local_err = NULL; int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, &local_err); if (local_err) { error_propagate(errp, local_err); -return; +return NULL; } if (slot >= mem_st->dev_count) { char *dev_path = object_get_canonical_path(OBJECT(dev)); -error_setg(errp, "acpi_memory_plug_cb: " +error_setg(errp, "acpi_memory_get_slot_status_descriptor: " "device [%s] returned invalid memory slot[%d]", -dev_path, slot); + dev_path, slot); g_free(dev_path); -return; +return NULL; } -mdev = &mem_st->devs[slot]; +return &mem_st->devs[slot]; +} + +void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, + DeviceState *dev, Error **errp) +{ +MemStatus *mdev; + +mdev = acpi_memory_get_slot_status_descriptor(mem_st, dev, errp); +if (!mdev) +return; + mdev->dimm = dev; mdev->is_enabled = true; mdev->is_inserting = true; -- 1.8.4.2
[Qemu-devel] [RESEND PATCH v1 06/13] acpi, ich9: Add memory hot unplug request support for ich9.
Call memory unplug request cb in ich9_pm_device_unplug_request_cb(). --- hw/acpi/ich9.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index c48d176..841f57d 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -304,8 +304,14 @@ void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp) void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp) { -error_setg(errp, "acpi: device unplug request for not supported device" - " type: %s", object_get_typename(OBJECT(dev))); +if (pm->acpi_memory_hotplug.is_enabled && +object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { +acpi_memory_unplug_request_cb(&pm->acpi_regs, pm->irq, + &pm->acpi_memory_hotplug, dev, errp); +} else { +error_setg(errp, "acpi: device unplug request for not supported device" + " type: %s", object_get_typename(OBJECT(dev))); +} } void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, -- 1.8.4.2
[Qemu-devel] [RESEND PATCH v1 01/13] acpi, mem-hotplug: Use PC_DIMM_SLOT_PROP in acpi_memory_plug_cb().
Replace string "slot" in acpi_memory_plug_cb() with MACRO PC_DIMM_SLOT_PROP. Signed-off-by: Tang Chen --- hw/acpi/memory_hotplug.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c index ed39241..c6580da 100644 --- a/hw/acpi/memory_hotplug.c +++ b/hw/acpi/memory_hotplug.c @@ -168,7 +168,8 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st, { MemStatus *mdev; Error *local_err = NULL; -int slot = object_property_get_int(OBJECT(dev), "slot", &local_err); +int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP, + &local_err); if (local_err) { error_propagate(errp, local_err); -- 1.8.4.2
[Qemu-devel] [RESEND PATCH v1 00/13] QEmu memory hot unplug support.
Memory hot unplug are both asynchronize procedures. When the unplug operation happens, unplug request cb is called first. And when ghest OS finished handling unplug, unplug cb will be called to do the real removal of device. This patch-set is based on QEmu 2.2 This series depends on the following patchset. [PATCH] Common unplug and unplug request cb for memory and CPU hot-unplug. https://www.mail-archive.com/qemu-devel@nongnu.org/msg272745.html Hu Tao (2): acpi, piix4: Add memory hot unplug request support for piix4. pc, acpi bios: Add memory hot unplug interface. Tang Chen (11): acpi, mem-hotplug: Use PC_DIMM_SLOT_PROP in acpi_memory_plug_cb(). acpi, mem-hotplug: Add acpi_memory_get_slot_status_descriptor() to get MemStatus. acpi, mem-hotplug: Add acpi_memory_hotplug_sci() to rise sci for memory hotplug. acpi, mem-hotplug: Add unplug request cb for memory device. acpi, ich9: Add memory hot unplug request support for ich9. pc-dimm: Add memory hot unplug request support for pc-dimm. acpi, mem-hotplug: Add unplug cb for memory device. acpi, piix4: Add memory hot unplug support for piix4. acpi, ich9: Add memory hot unplug support for ich9. pc-dimm: Add memory hot unplug support for pc-dimm. acpi: Add hardware implementation for memory hot unplug. docs/specs/acpi_mem_hotplug.txt | 8 +++- hw/acpi/ich9.c| 20 ++-- hw/acpi/memory_hotplug.c | 97 --- hw/acpi/piix4.c | 18 ++-- hw/core/qdev.c| 2 +- hw/i386/acpi-dsdt-mem-hotplug.dsl | 11 - hw/i386/pc.c | 53 +++-- hw/i386/ssdt-mem.dsl | 5 ++ include/hw/acpi/memory_hotplug.h | 6 +++ include/hw/acpi/pc-hotplug.h | 2 + include/hw/qdev-core.h| 1 + 11 files changed, 192 insertions(+), 31 deletions(-) -- 1.8.4.2
Re: [Qemu-devel] [PATCH v2] vfio-pci: Fix BAR size overflow
On 01/07/15 12:23, Alex Williamson wrote: > We use an unsigned int when working with the PCI BAR size, which can > obviously overflow if the BAR is 4GB or larger. This needs to change > to a fixed length uint64_t. A similar issue is possible, though even > more unlikely, when mapping the region above an MSI-X table. The > start of the MSI-X vector table must be below 4GB, but the end, and > therefore the start of the next mapping region, could still land at > 4GB. > > Suggested-by: Nishank Trivedi > Signed-off-by: Alex Williamson > --- > Looks good. Reviewed-by: Don Slutz -Don Slutz > v2: s/unsigned long/uint64_t/, duh > > hw/vfio/pci.c |4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c > index b4e73d1..b6703c7 100644 > --- a/hw/vfio/pci.c > +++ b/hw/vfio/pci.c > @@ -2301,7 +2301,7 @@ static void vfio_unmap_bar(VFIOPCIDevice *vdev, int nr) > static void vfio_map_bar(VFIOPCIDevice *vdev, int nr) > { > VFIOBAR *bar = &vdev->bars[nr]; > -unsigned size = bar->region.size; > +uint64_t size = bar->region.size; > char name[64]; > uint32_t pci_bar; > uint8_t type; > @@ -2351,7 +2351,7 @@ static void vfio_map_bar(VFIOPCIDevice *vdev, int nr) > } > > if (vdev->msix && vdev->msix->table_bar == nr) { > -unsigned start; > +uint64_t start; > > start = HOST_PAGE_ALIGN(vdev->msix->table_offset + > (vdev->msix->entries * PCI_MSIX_ENTRY_SIZE)); > >
[Qemu-devel] [PATCH] vfio-pci: Fix interrupt disabling
When disabling MSI/X interrupts the disable functions will leave the device in INTx mode (when available). This matches how hardware operates, INTx is enabled unless MSI/X is enabled (DisINTx is handled separately). Therefore when we really want to disable all interrupts, such as when removing the device, and we start with the device in MSI/X mode, we need to pass through INTx on our way to being completely quiesced. In well behaved situations, the guest driver will have shutdown the device and it will start vfio_exitfn() in INTx mode, producing the desired result. If hot-unplug causes the guest to crash, we may get the device in MSI/X state, which will leave QEMU with a bogus handler installed. Fix this by re-ordering our disable routine so that it should always finish in VFIO_INT_NONE state, which is what all callers expect. Signed-off-by: Alex Williamson --- hw/vfio/pci.c | 21 - 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index b6703c7..014a92c 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -2129,16 +2129,19 @@ static void vfio_pci_write_config(PCIDevice *pdev, uint32_t addr, */ static void vfio_disable_interrupts(VFIOPCIDevice *vdev) { -switch (vdev->interrupt) { -case VFIO_INT_INTx: -vfio_disable_intx(vdev); -break; -case VFIO_INT_MSI: -vfio_disable_msi(vdev); -break; -case VFIO_INT_MSIX: +/* + * More complicated than it looks. Disabling MSI/X transitions the + * device to INTx mode (if supported). Therefore we need to first + * disable MSI/X and then cleanup by disabling INTx. + */ +if (vdev->interrupt == VFIO_INT_MSIX) { vfio_disable_msix(vdev); -break; +} else if (vdev->interrupt == VFIO_INT_MSI) { +vfio_disable_msi(vdev); +} + +if (vdev->interrupt == VFIO_INT_INTx) { +vfio_disable_intx(vdev); } }
[Qemu-devel] [RFC PATCH] tests: rtl8139: test timers and interrupt
Test behaviour of timers and interrupts related to timeouts. Signed-off-by: Frediano Ziglio --- tests/Makefile | 2 +- tests/rtl8139-test.c | 164 +++ 2 files changed, 165 insertions(+), 1 deletion(-) This patch was derived from a test I did while implementing timer in rtl8139 code. Now that there is support for integrated testing I converted it. The test was tested on a real NIC. As if it's the first test I wrote I don't know if syntax and details are fine. For instance should I remove nop test? Should I split my test? diff --git a/tests/Makefile b/tests/Makefile index e4ddb6a..8858407 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -320,7 +320,7 @@ tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y) tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y) tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y) tests/e1000-test$(EXESUF): tests/e1000-test.o -tests/rtl8139-test$(EXESUF): tests/rtl8139-test.o +tests/rtl8139-test$(EXESUF): tests/rtl8139-test.o $(libqos-pc-obj-y) tests/pcnet-test$(EXESUF): tests/pcnet-test.o tests/eepro100-test$(EXESUF): tests/eepro100-test.o tests/vmxnet3-test$(EXESUF): tests/vmxnet3-test.o diff --git a/tests/rtl8139-test.c b/tests/rtl8139-test.c index f6a1be3..87f1792 100644 --- a/tests/rtl8139-test.c +++ b/tests/rtl8139-test.c @@ -10,19 +10,183 @@ #include #include #include "libqtest.h" +#include "libqos/pci-pc.h" #include "qemu/osdep.h" +#include "qemu-common.h" /* Tests only initialization so far. TODO: Replace with functional tests */ static void nop(void) { } +#define CLK 3300 +#define NS_PER_SEC 10ULL + +static QPCIBus *pcibus; +static QPCIDevice *dev = NULL; +static void *dev_base = NULL; + +static void save_fn(QPCIDevice *dev, int devfn, void *data) +{ +QPCIDevice **pdev = (QPCIDevice **) data; + +*pdev = dev; +} + +static QPCIDevice *get_device(void) +{ +QPCIDevice *dev; + +pcibus = qpci_init_pc(); +qpci_device_foreach(pcibus, 0x10ec, 0x8139, save_fn, &dev); +g_assert(dev != NULL); + +return dev; +} + +#define PORT(name,len,val) \ +static unsigned __attribute__((unused)) in_##name(void) { \ +unsigned res = qpci_io_read##len(dev,dev_base+(val)); \ +g_test_message("*%s -> %x\n", #name, res); \ +return res; \ +} \ +static void out_##name(unsigned v) { \ +g_test_message("%x -> *%s\n", v, #name); \ +qpci_io_write##len(dev,dev_base+(val),v); \ +} + +PORT(Timer,l,0x48) +PORT(IntrMask,w,0x3c) +PORT(IntrStatus,w,0x3E) +PORT(TimerInt,l,0x54) + +#define fatal(...) do { g_test_message(__VA_ARGS__); g_assert(0); } while(0) + +static void test_timer(void) +{ +const unsigned from = 0.95 * CLK; +const unsigned to = 1.6 * CLK; + +out_IntrMask(0); + +in_IntrStatus(); +in_Timer(); +in_Timer(); + +// Test 1. test counter continue and continue +out_TimerInt(0); // disable timer +out_IntrStatus(0x4000); +out_Timer(12345); // reset timer to 0 +unsigned curr = in_Timer(); +unsigned cnt; +if (curr > 0.1 * CLK) +fatal("time too big %u\n", curr); +for (cnt=0;;) { +clock_step(1 * NS_PER_SEC); +unsigned prev = curr; +curr = in_Timer(); + +// test skip is in a specific range +unsigned diff = (curr-prev) & 0xu; +if (diff < from || diff > to) +fatal("Invalid diff %u (%u-%u)\n", diff, from,to); +if (curr < prev && ++cnt == 3) +break; +} + +// Test 2. Check we didn't get an interrupt with TimerInt == 0 +if (in_IntrStatus() & 0x4000) +fatal("got an interrupt\n"); + +// Test 3. Setting TimerInt to 1 and Timer to 0 get interrupt +out_TimerInt(1); +out_Timer(0); +clock_step(40); +if ((in_IntrStatus() & 0x4000) == 0) +fatal("we should have an interrupt here!\n"); + +// Test 3. Check acknowledge +out_IntrStatus(0x4000); +if (in_IntrStatus() & 0x4000) +fatal("got an interrupt\n"); + +// Test. Status set after Timer reset +out_Timer(0); +out_TimerInt(0); +out_IntrStatus(0x4000); +curr = in_Timer(); +out_TimerInt(curr + 0.5 * CLK); +clock_step(1 * NS_PER_SEC); +out_Timer(0); +if ((in_IntrStatus() & 0x4000) == 0) +fatal("we should have an interrupt here!\n"); + +// Test. Status set after TimerInt reset +out_Timer(0); +out_TimerInt(0); +out_IntrStatus(0x4000); +curr = in_Timer(); +out_TimerInt(curr + 0.5 * CLK); +clock_step(1 * NS_PER_SEC); +out_TimerInt(0); +if ((in_IntrStatus() & 0x4000) == 0) +fatal("we should have an interrupt here!\n"); + +// Test 4. Increment TimerInt we should see an interrupt +curr = in_Timer(); +unsigned next = curr + 5.0 * CLK; +out_TimerInt(next); +for (cnt=0;;) { +clock_step(1 * NS_PER_SEC); +unsigned prev = curr; +curr = in_Timer(); +unsigned dif
Re: [Qemu-devel] [PATCH 3/4] arm: Add PCIe host bridge in virt machine
On 07.01.15 16:52, Claudio Fontana wrote: > On 06.01.2015 17:03, Alexander Graf wrote: >> Now that we have a working "generic" PCIe host bridge driver, we can plug >> it into ARMs virt machine to always have PCIe available to normal ARM VMs. >> >> I've successfully managed to expose a Bochs VGA device, XHCI and an e1000 >> into an AArch64 VM with this and they all lived happily ever after. >> >> Signed-off-by: Alexander Graf >> >> --- >> >> Linux 3.19 only supports the generic PCIe host bridge driver for 32bit ARM >> systems. If you want to use it with AArch64 guests, please apply the >> following >> patch or wait until upstream cleaned up the code properly: >> >> http://csgraf.de/agraf/pci/pci-3.19.patch >> --- >> default-configs/arm-softmmu.mak | 2 + >> hw/arm/virt.c | 83 >> ++--- >> 2 files changed, 80 insertions(+), 5 deletions(-) >> >> diff --git a/default-configs/arm-softmmu.mak >> b/default-configs/arm-softmmu.mak >> index f3513fa..7671ee2 100644 >> --- a/default-configs/arm-softmmu.mak >> +++ b/default-configs/arm-softmmu.mak >> @@ -82,6 +82,8 @@ CONFIG_ZYNQ=y >> CONFIG_VERSATILE_PCI=y >> CONFIG_VERSATILE_I2C=y >> >> +CONFIG_PCI_GENERIC=y >> + >> CONFIG_SDHCI=y >> CONFIG_INTEGRATOR_DEBUG=y >> >> diff --git a/hw/arm/virt.c b/hw/arm/virt.c >> index 2353440..b7635ac 100644 >> --- a/hw/arm/virt.c >> +++ b/hw/arm/virt.c >> @@ -42,6 +42,7 @@ >> #include "exec/address-spaces.h" >> #include "qemu/bitops.h" >> #include "qemu/error-report.h" >> +#include "hw/pci-host/gpex.h" >> >> #define NUM_VIRTIO_TRANSPORTS 32 >> >> @@ -69,6 +70,7 @@ enum { >> VIRT_MMIO, >> VIRT_RTC, >> VIRT_FW_CFG, >> +VIRT_PCIE, >> }; >> >> typedef struct MemMapEntry { >> @@ -129,13 +131,14 @@ static const MemMapEntry a15memmap[] = { >> [VIRT_FW_CFG] = { 0x0902, 0x000a }, >> [VIRT_MMIO] = { 0x0a00, 0x0200 }, >> /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size >> */ >> -/* 0x1000 .. 0x4000 reserved for PCI */ >> +[VIRT_PCIE] = { 0x1000, 0x3000 }, >> [VIRT_MEM] ={ 0x4000, 30ULL * 1024 * 1024 * 1024 }, >> }; >> >> static const int a15irqmap[] = { >> [VIRT_UART] = 1, >> [VIRT_RTC] = 2, >> +[VIRT_PCIE] = 3, >> [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ >> }; >> >> @@ -312,7 +315,7 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi) >> } >> } >> >> -static void fdt_add_gic_node(const VirtBoardInfo *vbi) >> +static uint32_t fdt_add_gic_node(const VirtBoardInfo *vbi) >> { >> uint32_t gic_phandle; >> >> @@ -331,9 +334,11 @@ static void fdt_add_gic_node(const VirtBoardInfo *vbi) >> 2, vbi->memmap[VIRT_GIC_CPU].base, >> 2, vbi->memmap[VIRT_GIC_CPU].size); >> qemu_fdt_setprop_cell(vbi->fdt, "/intc", "phandle", gic_phandle); >> + >> +return gic_phandle; >> } >> >> -static void create_gic(const VirtBoardInfo *vbi, qemu_irq *pic) >> +static uint32_t create_gic(const VirtBoardInfo *vbi, qemu_irq *pic) >> { >> /* We create a standalone GIC v2 */ >> DeviceState *gicdev; >> @@ -380,7 +385,7 @@ static void create_gic(const VirtBoardInfo *vbi, >> qemu_irq *pic) >> pic[i] = qdev_get_gpio_in(gicdev, i); >> } >> >> -fdt_add_gic_node(vbi); >> +return fdt_add_gic_node(vbi); >> } >> >> static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic) >> @@ -556,6 +561,71 @@ static void create_fw_cfg(const VirtBoardInfo *vbi) >> g_free(nodename); >> } >> >> +static void create_pcie(const VirtBoardInfo *vbi, qemu_irq *pic, >> +uint32_t gic_phandle) >> +{ >> +hwaddr base = vbi->memmap[VIRT_PCIE].base; >> +hwaddr size = vbi->memmap[VIRT_PCIE].size; >> +hwaddr size_ioport = 64 * 1024; >> +hwaddr size_ecam = PCIE_MMCFG_SIZE_MIN; >> +hwaddr size_mmio = size - size_ecam - size_ioport; >> +hwaddr base_mmio = base; >> +hwaddr base_ioport = base_mmio + size_mmio; >> +hwaddr base_ecam = base_ioport + size_ioport; >> +int irq = vbi->irqmap[VIRT_PCIE]; >> +MemoryRegion *mmio_alias; >> +MemoryRegion *mmio_reg; >> +DeviceState *dev; >> +char *nodename; >> + >> +dev = qdev_create(NULL, TYPE_GPEX_HOST); >> + >> +qdev_prop_set_uint64(dev, "mmio_window_size", size_mmio); >> +qdev_init_nofail(dev); >> + >> +sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base_ecam); >> +sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, base_ioport); >> + >> +/* Map the MMIO window at the same spot in bus and cpu layouts */ >> +mmio_alias = g_new0(MemoryRegion, 1); >> +mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); >> +memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio", >> + mmio_reg, base_mmio, size_mmio); >> +memory_region_add_subregion(get_s
[Qemu-devel] [PATCH v9 7/7] netduino2: Add the Netduino 2 Machine
This patch adds the Netduino 2 Machine. This is a Cortex-M3 based machine. Information can be found at: http://www.netduino.com/netduino2/specs.htm Signed-off-by: Alistair Francis --- hw/arm/Makefile.objs | 1 + hw/arm/netduino2.c | 54 2 files changed, 55 insertions(+) create mode 100644 hw/arm/netduino2.c diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 9769317..2577f68 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -3,6 +3,7 @@ obj-$(CONFIG_DIGIC) += digic_boards.o obj-y += integratorcp.o kzm.o mainstone.o musicpal.o nseries.o obj-y += omap_sx1.o palm.o realview.o spitz.o stellaris.o obj-y += tosa.o versatilepb.o vexpress.o virt.o xilinx_zynq.o z2.o +obj-y += netduino2.o obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o obj-$(CONFIG_DIGIC) += digic.o diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c new file mode 100644 index 000..305983f --- /dev/null +++ b/hw/arm/netduino2.c @@ -0,0 +1,54 @@ +/* + * Netduino 2 Machine Model + * + * Copyright (c) 2014 Alistair Francis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw/arm/stm32f205_soc.h" + +static void netduino2_init(MachineState *machine) +{ +DeviceState *dev; +Error *err = NULL; + +dev = qdev_create(NULL, TYPE_STM32F205_SOC); +if (machine->kernel_filename) { +qdev_prop_set_string(dev, "kernel-filename", machine->kernel_filename); +} +object_property_set_bool(OBJECT(dev), true, "realized", &err); +if (err != NULL) { +error_report("%s", error_get_pretty(err)); +exit(1); +} +} + +static QEMUMachine netduino2_machine = { +.name = "netduino2", +.desc = "Netduino 2 Machine", +.init = netduino2_init, +}; + +static void netduino2_machine_init(void) +{ +qemu_register_machine(&netduino2_machine); +} + +machine_init(netduino2_machine_init); -- 2.1.0
[Qemu-devel] [PATCH v9 1/7] stm32f2xx_timer: Add the stm32f2xx Timer
This patch adds the stm32f2xx timers: TIM2, TIM3, TIM4 and TIM5 to QEMU. Signed-off-by: Alistair Francis --- V9: - Convert tick_offset to now be updated on more events - This is similar to what I did with the ARM PCCNT regiseter V8: - Fix tick_offset to allow now to wrap around - Remove the calls to get_ticks_per_sec() - Pre-scale the guest visable time V6: - Rename to STM32F2XX - Change the timer calculations to use ns - Update the value to timer_mod to ensure it is in ns - Account for reloadable/resetable timer - Thanks to Peter C for pointing this out V4: - Update timer units again - Thanks to Peter C V3: - Update debug statements - Correct the units for timer_mod - Correctly set timer_offset from resets V2: - Reorder the Makefile config - Fix up the debug printing - Correct the timer event trigger default-configs/arm-softmmu.mak| 1 + hw/timer/Makefile.objs | 2 + hw/timer/stm32f2xx_timer.c | 330 + include/hw/timer/stm32f2xx_timer.h | 101 4 files changed, 434 insertions(+) create mode 100644 hw/timer/stm32f2xx_timer.c create mode 100644 include/hw/timer/stm32f2xx_timer.h diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index f3513fa..faea100 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -78,6 +78,7 @@ CONFIG_NSERIES=y CONFIG_REALVIEW=y CONFIG_ZAURUS=y CONFIG_ZYNQ=y +CONFIG_STM32F2XX_TIMER=y CONFIG_VERSATILE_PCI=y CONFIG_VERSATILE_I2C=y diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs index 2c86c3d..133bd0d 100644 --- a/hw/timer/Makefile.objs +++ b/hw/timer/Makefile.objs @@ -31,3 +31,5 @@ obj-$(CONFIG_DIGIC) += digic-timer.o obj-$(CONFIG_MC146818RTC) += mc146818rtc.o obj-$(CONFIG_ALLWINNER_A10_PIT) += allwinner-a10-pit.o + +common-obj-$(CONFIG_STM32F2XX_TIMER) += stm32f2xx_timer.o diff --git a/hw/timer/stm32f2xx_timer.c b/hw/timer/stm32f2xx_timer.c new file mode 100644 index 000..518ecc9 --- /dev/null +++ b/hw/timer/stm32f2xx_timer.c @@ -0,0 +1,330 @@ +/* + * STM32F2XX Timer + * + * Copyright (c) 2014 Alistair Francis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw/timer/stm32f2xx_timer.h" + +#ifndef STM_TIMER_ERR_DEBUG +#define STM_TIMER_ERR_DEBUG 0 +#endif + +#define DB_PRINT_L(lvl, fmt, args...) do { \ +if (STM_TIMER_ERR_DEBUG >= lvl) { \ +qemu_log("%s: " fmt, __func__, ## args); \ +} \ +} while (0); + +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) + +static void stm32f2xx_timer_set_alarm(STM32F2XXTimerState *s); + +static void stm32f2xx_timer_interrupt(void *opaque) +{ +STM32F2XXTimerState *s = opaque; + +DB_PRINT("Interrupt\n"); + +if (s->tim_dier & TIM_DIER_UIE && s->tim_cr1 & TIM_CR1_CEN) { +s->tim_sr |= 1; +qemu_irq_pulse(s->irq); +stm32f2xx_timer_set_alarm(s); +} +} + +static void stm32f2xx_timer_set_alarm(STM32F2XXTimerState *s) +{ +uint32_t ticks; +int64_t now, wait_time; + +DB_PRINT("Alarm set at: 0x%x\n", s->tim_cr1); + +now = muldiv64(s->freq_hz, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + 10ULL); + +ticks = s->tim_arr - ((now / (s->tim_psc + 1)) - s->tick_offset); + +DB_PRINT("Alarm set in %d ticks\n", ticks); + +if (ticks == 0) { +timer_del(s->timer); +stm32f2xx_timer_interrupt(s); +} else { +wait_time = muldiv64(now + ticks, 10ULL, s->freq_hz); + +timer_mod(s->timer, wait_time); +DB_PRINT("Wait Time: %" PRId64 " ticks\n", wait_time); +} +} + +static void stm32f2xx_timer_reset(DeviceState *dev) +{ +STM32F2XXTimerState *s = STM32F2XXTIMER(dev); + +s->tim_cr1 = 0; +s->tim_cr2 = 0; +s->tim_smcr = 0; +s->tim_dier = 0; +s->tim_sr = 0; +s->tim_egr = 0; +s->tim_ccmr1 = 0; +s->tim_ccmr2 = 0; +s->tim_ccer = 0; +s->tim_cnt = 0;
[Qemu-devel] [PATCH v9 3/7] stm32f2xx_SYSCFG: Add the stm32f2xx SYSCFG
This patch adds the stm32f2xx System Configuration Controller. This is used to configure what memory is mapped at address 0 (although that is not supported) as well as configure how the EXTI interrupts work (also not supported at the moment). This device is not required for basic examples, but more complex systems will require it (as well as the EXTI device) Signed-off-by: Alistair Francis Reviewed-by: Peter Crosthwaite --- V6: - Rename to STM32F2XX - Remove all casts from debug printing V5: - Correct the masks used for writing V3: - Update debug printing default-configs/arm-softmmu.mak| 1 + hw/misc/Makefile.objs | 1 + hw/misc/stm32f2xx_syscfg.c | 160 + include/hw/misc/stm32f2xx_syscfg.h | 61 ++ 4 files changed, 223 insertions(+) create mode 100644 hw/misc/stm32f2xx_syscfg.c create mode 100644 include/hw/misc/stm32f2xx_syscfg.h diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index 1348104..a5aab7f 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -80,6 +80,7 @@ CONFIG_ZAURUS=y CONFIG_ZYNQ=y CONFIG_STM32F2XX_TIMER=y CONFIG_STM32F2XX_USART=y +CONFIG_STM32F2XX_SYSCFG=y CONFIG_VERSATILE_PCI=y CONFIG_VERSATILE_I2C=y diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs index e47fea8..ea5abb6 100644 --- a/hw/misc/Makefile.objs +++ b/hw/misc/Makefile.objs @@ -38,5 +38,6 @@ obj-$(CONFIG_OMAP) += omap_sdrc.o obj-$(CONFIG_OMAP) += omap_tap.o obj-$(CONFIG_SLAVIO) += slavio_misc.o obj-$(CONFIG_ZYNQ) += zynq_slcr.o +obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o obj-$(CONFIG_PVPANIC) += pvpanic.o diff --git a/hw/misc/stm32f2xx_syscfg.c b/hw/misc/stm32f2xx_syscfg.c new file mode 100644 index 000..4ae4042 --- /dev/null +++ b/hw/misc/stm32f2xx_syscfg.c @@ -0,0 +1,160 @@ +/* + * STM32F2XX SYSCFG + * + * Copyright (c) 2014 Alistair Francis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw/misc/stm32f2xx_syscfg.h" + +#ifndef STM_SYSCFG_ERR_DEBUG +#define STM_SYSCFG_ERR_DEBUG 0 +#endif + +#define DB_PRINT_L(lvl, fmt, args...) do { \ +if (STM_SYSCFG_ERR_DEBUG >= lvl) { \ +qemu_log("%s: " fmt, __func__, ## args); \ +} \ +} while (0); + +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) + +static void stm32f2xx_syscfg_reset(DeviceState *dev) +{ +STM32F2XXSyscfgState *s = STM32F2XX_SYSCFG(dev); + +s->syscfg_memrmp = 0x; +s->syscfg_pmc = 0x; +s->syscfg_exticr1 = 0x; +s->syscfg_exticr2 = 0x; +s->syscfg_exticr3 = 0x; +s->syscfg_exticr4 = 0x; +s->syscfg_cmpcr = 0x; +} + +static uint64_t stm32f2xx_syscfg_read(void *opaque, hwaddr addr, + unsigned int size) +{ +STM32F2XXSyscfgState *s = opaque; + +DB_PRINT("0x%"HWADDR_PRIx"\n", addr); + +switch (addr) { +case SYSCFG_MEMRMP: +return s->syscfg_memrmp; +case SYSCFG_PMC: +return s->syscfg_pmc; +case SYSCFG_EXTICR1: +return s->syscfg_exticr1; +case SYSCFG_EXTICR2: +return s->syscfg_exticr2; +case SYSCFG_EXTICR3: +return s->syscfg_exticr3; +case SYSCFG_EXTICR4: +return s->syscfg_exticr4; +case SYSCFG_CMPCR: +return s->syscfg_cmpcr; +default: +qemu_log_mask(LOG_GUEST_ERROR, + "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr); +return 0; +} + +return 0; +} + +static void stm32f2xx_syscfg_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ +STM32F2XXSyscfgState *s = opaque; +uint32_t value = val64; + +DB_PRINT("0x%x, 0x%"HWADDR_PRIx"\n", value, addr); + +switch (addr) { +case SYSCFG_MEMRMP: +qemu_log_mask(LOG_UNIMP, + "%s: Changeing the memory mapping isn't supported " \ +
[Qemu-devel] [PATCH v9 6/7] stm32f205: Add the stm32f205 SoC
This patch adds the stm32f205 SoC. This will be used by the Netduino 2 to create a machine. Signed-off-by: Alistair Francis --- V6: - Correct the number of USART/UART devices - Use macros to define how many devices are inited - Update the memory regions name from netduino.* to STM32F205.* default-configs/arm-softmmu.mak | 1 + hw/arm/Makefile.objs| 1 + hw/arm/stm32f205_soc.c | 157 include/hw/arm/stm32f205_soc.h | 69 ++ 4 files changed, 228 insertions(+) create mode 100644 hw/arm/stm32f205_soc.c create mode 100644 include/hw/arm/stm32f205_soc.h diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index a5aab7f..9ac755e 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -81,6 +81,7 @@ CONFIG_ZYNQ=y CONFIG_STM32F2XX_TIMER=y CONFIG_STM32F2XX_USART=y CONFIG_STM32F2XX_SYSCFG=y +CONFIG_STM32F205_SOC=y CONFIG_VERSATILE_PCI=y CONFIG_VERSATILE_I2C=y diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs index 6088e53..9769317 100644 --- a/hw/arm/Makefile.objs +++ b/hw/arm/Makefile.objs @@ -8,3 +8,4 @@ obj-y += armv7m.o exynos4210.o pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o obj-$(CONFIG_DIGIC) += digic.o obj-y += omap1.o omap2.o strongarm.o obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o +obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c new file mode 100644 index 000..186e15d --- /dev/null +++ b/hw/arm/stm32f205_soc.c @@ -0,0 +1,157 @@ +/* + * STM32F205 SoC + * + * Copyright (c) 2014 Alistair Francis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw/arm/stm32f205_soc.h" + +/* At the moment only Timer 2 to 5 are modelled */ +static const uint32_t timer_addr[STM_NUM_TIMERS] = { 0x4000, 0x4400, +0x4800, 0x4C00 }; +static const uint32_t usart_addr[STM_NUM_USARTS] = { 0x40011000, 0x40004400, +0x40004800, 0x40004C00, 0x40005000, 0x40011400 }; + +static const int timer_irq[STM_NUM_TIMERS] = {28, 29, 30, 50}; +static const int usart_irq[STM_NUM_USARTS] = {37, 38, 39, 52, 53, 71}; + +static void stm32f205_soc_initfn(Object *obj) +{ +STM32F205State *s = STM32F205_SOC(obj); +int i; + +object_initialize(&s->syscfg, sizeof(s->syscfg), TYPE_STM32F2XX_SYSCFG); +qdev_set_parent_bus(DEVICE(&s->syscfg), sysbus_get_default()); + +for (i = 0; i < STM_NUM_USARTS; i++) { +object_initialize(&s->usart[i], sizeof(s->usart[i]), + TYPE_STM32F2XX_USART); +qdev_set_parent_bus(DEVICE(&s->usart[i]), sysbus_get_default()); +} + +for (i = 0; i < STM_NUM_TIMERS; i++) { +object_initialize(&s->timer[i], sizeof(s->timer[i]), + TYPE_STM32F2XX_TIMER); +qdev_set_parent_bus(DEVICE(&s->timer[i]), sysbus_get_default()); +} +} + +static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) +{ +STM32F205State *s = STM32F205_SOC(dev_soc); +DeviceState *syscfgdev, *usartdev, *timerdev; +SysBusDevice *syscfgbusdev, *usartbusdev, *timerbusdev; +qemu_irq *pic; +Error *err = NULL; +int i; + +MemoryRegion *system_memory = get_system_memory(); +MemoryRegion *sram = g_new(MemoryRegion, 1); +MemoryRegion *flash = g_new(MemoryRegion, 1); +MemoryRegion *flash_alias = g_new(MemoryRegion, 1); + +memory_region_init_ram(flash, NULL, "STM32F205.flash", FLASH_SIZE, + &error_abort); +memory_region_init_alias(flash_alias, NULL, "STM32F205.flash.alias", + flash, 0, FLASH_SIZE); + +vmstate_register_ram_global(flash); + +memory_region_set_readonly(flash, true); +memory_region_set_readonly(flash_alias, true); + +memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash); +memory_region_add_subregion(system_memory, 0, flash_al
[Qemu-devel] [PATCH v9 4/7] target_arm: Remove memory region init from armv7m_init
This patch moves the memory region init code from the armv7m_init function to the stellaris_init function Signed-off-by: Alistair Francis Reviewed-by: Peter Crosthwaite --- V3: - Rename the flash_size argument to mem_size - Remove the sram_size and related code - Thanks to Peter C V2: - Change the memory region names to match the machine hw/arm/armv7m.c | 33 +++-- hw/arm/stellaris.c | 24 include/hw/arm/arm.h | 3 +-- 3 files changed, 24 insertions(+), 36 deletions(-) diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index ef24ca4..50281f7 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -163,11 +163,10 @@ static void armv7m_reset(void *opaque) } /* Init CPU and memory for a v7-M based board. - flash_size and sram_size are in kb. + mem_size is in bytes. Returns the NVIC array. */ -qemu_irq *armv7m_init(MemoryRegion *system_memory, - int flash_size, int sram_size, +qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, const char *kernel_filename, const char *cpu_model) { ARMCPU *cpu; @@ -180,13 +179,8 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, uint64_t lowaddr; int i; int big_endian; -MemoryRegion *sram = g_new(MemoryRegion, 1); -MemoryRegion *flash = g_new(MemoryRegion, 1); MemoryRegion *hack = g_new(MemoryRegion, 1); -flash_size *= 1024; -sram_size *= 1024; - if (cpu_model == NULL) { cpu_model = "cortex-m3"; } @@ -197,27 +191,6 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, } env = &cpu->env; -#if 0 -/* > 32Mb SRAM gets complicated because it overlaps the bitband area. - We don't have proper commandline options, so allocate half of memory - as SRAM, up to a maximum of 32Mb, and the rest as code. */ -if (ram_size > (512 + 32) * 1024 * 1024) -ram_size = (512 + 32) * 1024 * 1024; -sram_size = (ram_size / 2) & TARGET_PAGE_MASK; -if (sram_size > 32 * 1024 * 1024) -sram_size = 32 * 1024 * 1024; -code_size = ram_size - sram_size; -#endif - -/* Flash programming is done via the SCU, so pretend it is ROM. */ -memory_region_init_ram(flash, NULL, "armv7m.flash", flash_size, - &error_abort); -vmstate_register_ram_global(flash); -memory_region_set_readonly(flash, true); -memory_region_add_subregion(system_memory, 0, flash); -memory_region_init_ram(sram, NULL, "armv7m.sram", sram_size, &error_abort); -vmstate_register_ram_global(sram); -memory_region_add_subregion(system_memory, 0x2000, sram); armv7m_bitband_init(); nvic = qdev_create(NULL, "armv7m_nvic"); @@ -244,7 +217,7 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr, NULL, big_endian, ELF_MACHINE, 1); if (image_size < 0) { -image_size = load_image_targphys(kernel_filename, 0, flash_size); +image_size = load_image_targphys(kernel_filename, 0, mem_size); lowaddr = 0; } if (image_size < 0) { diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 64bd4b4..d0c61c5 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -1220,10 +1220,26 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, int i; int j; -flash_size = ((board->dc0 & 0x) + 1) << 1; -sram_size = (board->dc0 >> 18) + 1; -pic = armv7m_init(get_system_memory(), - flash_size, sram_size, kernel_filename, cpu_model); +MemoryRegion *sram = g_new(MemoryRegion, 1); +MemoryRegion *flash = g_new(MemoryRegion, 1); +MemoryRegion *system_memory = get_system_memory(); + +flash_size = (((board->dc0 & 0x) + 1) << 1) * 1024; +sram_size = ((board->dc0 >> 18) + 1) * 1024; + +/* Flash programming is done via the SCU, so pretend it is ROM. */ +memory_region_init_ram(flash, NULL, "stellaris.flash", flash_size, + &error_abort); +vmstate_register_ram_global(flash); +memory_region_set_readonly(flash, true); +memory_region_add_subregion(system_memory, 0, flash); + +memory_region_init_ram(sram, NULL, "stellaris.sram", sram_size, + &error_abort); +vmstate_register_ram_global(sram); +memory_region_add_subregion(system_memory, 0x2000, sram); + +pic = armv7m_init(system_memory, flash_size, kernel_filename, cpu_model); if (board->dc1 & (1 << 16)) { dev = sysbus_create_varargs(TYPE_STELLARIS_ADC, 0x40038000, diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h index c4bf56d..f8b329b 100644 --- a/include/hw/arm/arm.h +++ b/include/hw/arm/arm.h @@ -15,8 +15,7 @@ #include "hw/irq.h" /* armv7m.c */ -qemu_irq *armv7m_init(MemoryRegion *system_memory, - int flash_size, in
[Qemu-devel] [PATCH v9 5/7] target_arm: Parameterise the irq lines for armv7m_init
This patch allows the board to specifiy the number of NVIC interrupt lines when using armv7m_init. Signed-off-by: Alistair Francis Reviewed-by: Peter Crosthwaite --- hw/arm/armv7m.c | 7 --- hw/arm/stellaris.c | 5 - include/hw/arm/arm.h | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index 50281f7..7169027 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -166,14 +166,14 @@ static void armv7m_reset(void *opaque) mem_size is in bytes. Returns the NVIC array. */ -qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, +qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, const char *kernel_filename, const char *cpu_model) { ARMCPU *cpu; CPUARMState *env; DeviceState *nvic; /* FIXME: make this local state. */ -static qemu_irq pic[64]; +qemu_irq *pic = g_new(qemu_irq, num_irq); int image_size; uint64_t entry; uint64_t lowaddr; @@ -194,11 +194,12 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, armv7m_bitband_init(); nvic = qdev_create(NULL, "armv7m_nvic"); +qdev_prop_set_uint32(nvic, "num-irq", num_irq); env->nvic = nvic; qdev_init_nofail(nvic); sysbus_connect_irq(SYS_BUS_DEVICE(nvic), 0, qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ)); -for (i = 0; i < 64; i++) { +for (i = 0; i < num_irq; i++) { pic[i] = qdev_get_gpio_in(nvic, i); } diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index d0c61c5..6fad10f 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -29,6 +29,8 @@ #define BP_OLED_SSI 0x02 #define BP_GAMEPAD 0x04 +#define NUM_IRQ_LINES 64 + typedef const struct { const char *name; uint32_t did0; @@ -1239,7 +1241,8 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, vmstate_register_ram_global(sram); memory_region_add_subregion(system_memory, 0x2000, sram); -pic = armv7m_init(system_memory, flash_size, kernel_filename, cpu_model); +pic = armv7m_init(system_memory, flash_size, NUM_IRQ_LINES, + kernel_filename, cpu_model); if (board->dc1 & (1 << 16)) { dev = sysbus_create_varargs(TYPE_STELLARIS_ADC, 0x40038000, diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h index f8b329b..5c940eb 100644 --- a/include/hw/arm/arm.h +++ b/include/hw/arm/arm.h @@ -15,7 +15,7 @@ #include "hw/irq.h" /* armv7m.c */ -qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, +qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq, const char *kernel_filename, const char *cpu_model); /* arm_boot.c */ -- 2.1.0
[Qemu-devel] [PATCH v9 2/7] stm32f2xx_USART: Add the stm32f2xx USART Controller
This patch adds the stm32f2xx USART controller (UART also uses the same controller). Signed-off-by: Alistair Francis --- V8: - Clear IRQ on reset - Lower IRQ on data read/status clear - Set IRQ if enabled while data is avaliable V6: - Rename to STM32F2XX - Fix up unimplemented printing - Add a qemu_chr_accept() V3: - Update debug printing V2: - Drop charecters if the device is not enabled - Thanks to Peter C default-configs/arm-softmmu.mak | 1 + hw/char/Makefile.objs | 1 + hw/char/stm32f2xx_usart.c | 229 ++ include/hw/char/stm32f2xx_usart.h | 69 4 files changed, 300 insertions(+) create mode 100644 hw/char/stm32f2xx_usart.c create mode 100644 include/hw/char/stm32f2xx_usart.h diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index faea100..1348104 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -79,6 +79,7 @@ CONFIG_REALVIEW=y CONFIG_ZAURUS=y CONFIG_ZYNQ=y CONFIG_STM32F2XX_TIMER=y +CONFIG_STM32F2XX_USART=y CONFIG_VERSATILE_PCI=y CONFIG_VERSATILE_I2C=y diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs index 317385d..5931cc8 100644 --- a/hw/char/Makefile.objs +++ b/hw/char/Makefile.objs @@ -15,6 +15,7 @@ obj-$(CONFIG_OMAP) += omap_uart.o obj-$(CONFIG_SH4) += sh_serial.o obj-$(CONFIG_PSERIES) += spapr_vty.o obj-$(CONFIG_DIGIC) += digic-uart.o +obj-$(CONFIG_STM32F2XX_USART) += stm32f2xx_usart.o common-obj-$(CONFIG_ETRAXFS) += etraxfs_ser.o common-obj-$(CONFIG_ISA_DEBUG) += debugcon.o diff --git a/hw/char/stm32f2xx_usart.c b/hw/char/stm32f2xx_usart.c new file mode 100644 index 000..260b053 --- /dev/null +++ b/hw/char/stm32f2xx_usart.c @@ -0,0 +1,229 @@ +/* + * STM32F2XX USART + * + * Copyright (c) 2014 Alistair Francis + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw/char/stm32f2xx_usart.h" + +#ifndef STM_USART_ERR_DEBUG +#define STM_USART_ERR_DEBUG 0 +#endif + +#define DB_PRINT_L(lvl, fmt, args...) do { \ +if (STM_USART_ERR_DEBUG >= lvl) { \ +qemu_log("%s: " fmt, __func__, ## args); \ +} \ +} while (0); + +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) + +static int stm32f2xx_usart_can_receive(void *opaque) +{ +STM32F2XXUsartState *s = opaque; + +if (!(s->usart_sr & USART_SR_RXNE)) { +return 1; +} + +return 0; +} + +static void stm32f2xx_usart_receive(void *opaque, const uint8_t *buf, int size) +{ +STM32F2XXUsartState *s = opaque; + +s->usart_dr = *buf; + +if (!(s->usart_cr1 & USART_CR1_UE && s->usart_cr1 & USART_CR1_RE)) { +/* USART not enabled - drop the chars */ +DB_PRINT("Dropping the chars\n"); +return; +} + +s->usart_sr |= USART_SR_RXNE; + +if (s->usart_cr1 & USART_CR1_RXNEIE) { +qemu_set_irq(s->irq, 1); +} + +DB_PRINT("Receiving: %c\n", s->usart_dr); +} + +static void stm32f2xx_usart_reset(DeviceState *dev) +{ +STM32F2XXUsartState *s = STM32F2XX_USART(dev); + +s->usart_sr = USART_SR_RESET; +s->usart_dr = 0x; +s->usart_brr = 0x; +s->usart_cr1 = 0x; +s->usart_cr2 = 0x; +s->usart_cr3 = 0x; +s->usart_gtpr = 0x; + +qemu_set_irq(s->irq, 0); +} + +static uint64_t stm32f2xx_usart_read(void *opaque, hwaddr addr, + unsigned int size) +{ +STM32F2XXUsartState *s = opaque; +uint64_t retvalue; + +DB_PRINT("Read 0x%"HWADDR_PRIx"\n", addr); + +switch (addr) { +case USART_SR: +retvalue = s->usart_sr; +s->usart_sr &= ~USART_SR_TC; +if (s->chr) { +qemu_chr_accept_input(s->chr); +} +return retvalue; +case USART_DR: +DB_PRINT("Value: 0x%" PRIx32 ", %c\n", s->usart_dr, (char) s->usart_dr); +s->usart_sr |= USART_SR_TXE; +s->usart_sr &= ~USART_SR_RXNE; +
[Qemu-devel] [PATCH v9 0/7] Netduino 2 Machine Model
This patch series adds the Netduino 2 Machine to QEMU Information on the board is avalible at: http://www.netduino.com/netduino2/specs.htm The git tree can be found at: https://github.com/alistair23/qemu/tree/netduino2.9 This patch series makes some changes to the armv7m_init function that allows the code to be reused with the Netduino 2 and the Stellaris machines. Some example code that runs on QEMU is avaliable at: at: https://github.com/alistair23/CSSE3010-QEMU-Examples There are more devices in the works, I figured I would just start with these three V9: - Correct timer device based on Peter C's comments V8: - Update the timer device based on Peter C's comments - Update the USART device based on Peter C's comments V7: - Rebase to QEMU 2.2 V6: - Rename the three devices to STM32FXX* - Correct the timer to use ns - Correct the number of devices that are inited - Rename memory regions V5: - Remove the reset changes based on the ELF entry V4: - Rebase - Correct timer units V3: - Correct the timer interrupts - Update debug printing - Remove the sram_size argument from armv7m_init Alistair Francis (7): stm32f2xx_timer: Add the stm32f2xx Timer stm32f2xx_USART: Add the stm32f2xx USART Controller stm32f2xx_SYSCFG: Add the stm32f2xx SYSCFG target_arm: Remove memory region init from armv7m_init target_arm: Parameterise the irq lines for armv7m_init stm32f205: Add the stm32f205 SoC netduino2: Add the Netduino 2 Machine default-configs/arm-softmmu.mak| 4 + hw/arm/Makefile.objs | 2 + hw/arm/armv7m.c| 38 + hw/arm/netduino2.c | 54 ++ hw/arm/stellaris.c | 27 ++- hw/arm/stm32f205_soc.c | 157 ++ hw/char/Makefile.objs | 1 + hw/char/stm32f2xx_usart.c | 229 + hw/misc/Makefile.objs | 1 + hw/misc/stm32f2xx_syscfg.c | 160 ++ hw/timer/Makefile.objs | 2 + hw/timer/stm32f2xx_timer.c | 330 + include/hw/arm/arm.h | 3 +- include/hw/arm/stm32f205_soc.h | 69 include/hw/char/stm32f2xx_usart.h | 69 include/hw/misc/stm32f2xx_syscfg.h | 61 +++ include/hw/timer/stm32f2xx_timer.h | 101 17 files changed, 1270 insertions(+), 38 deletions(-) create mode 100644 hw/arm/netduino2.c create mode 100644 hw/arm/stm32f205_soc.c create mode 100644 hw/char/stm32f2xx_usart.c create mode 100644 hw/misc/stm32f2xx_syscfg.c create mode 100644 hw/timer/stm32f2xx_timer.c create mode 100644 include/hw/arm/stm32f205_soc.h create mode 100644 include/hw/char/stm32f2xx_usart.h create mode 100644 include/hw/misc/stm32f2xx_syscfg.h create mode 100644 include/hw/timer/stm32f2xx_timer.h -- 2.1.0
Re: [Qemu-devel] [PATCH v3 0/8] acpi: make ROMs resizeable
On 07/01/2015 20:48, Michael S. Tsirkin wrote: > This is v3 of the patchset. > Changes since v2: > - Address Paolo's comments: drop an unused function, fix up > comment. > > Changes since v1: > - Any RAM can now be resizeable - there's no requirement > that it's device RAM any longer. > - For simplicity, max_size RAM is always pre-allocated > - Added memory_region_set_size, to keep MR size consistent > in case MR is guest visible (even though for current users, > it never is) > > At the moment we migrate ROMs which reside in fw cfg, which allows > changing ROM code at will, and supports migrating largish blocks early, > with good performance. > However, we are running into a problem: changing size breaks > migration every time. > This already requires somewhat messy compatibility support in > acpi generation code, and it looks like there'll be more to come. > > While recent patches by Paolo and others might make it easier > to keep table size static for specific machine types, having > a safety net in case we do need to change it sounds like > a good idea. > > Rather than try to guess the correct size once and for all, > this patchset tries to make code future-proof, by > adding support for resizeable ram blocks. > > A (possibly very high) amount of space in ram_addr_t space is reserved > and allocated in host for each block, but never used by fw cfg. > If incoming block size differs from current size, block is > reallocated. FW CFG is also notified and updated accordingly. > > As reviewers felt that making all RAM "resizeable" in this > way might make debugging migration harder, these patches > set a per-block flag and only allow resizing for blocks > where this was explicitly requested. > > Note: migration stream is unaffected by these patches. > This makes it possible to enable this functionality > unconditionally, for all machine types. > > In the future, this API might be handy for other things, besides ROMs. Ok for 2.3, just squash 4 and 8 together. No need to repost. Reviewed-by: Paolo Bonzini
Re: [Qemu-devel] [PATCH v3] configure: Simplify alternate .text segment
On 7 January 2015 at 18:02, Stefan Weil wrote: > Hello, > > this patch which is part of QEMU for more than a year now needs to be fixed > for builds on Mac OS X: > I just saw that the Mac's native linker ld does not support --verbose, but > shows a warning. Cosmetically ugly, but not a show stopper :-) I haven't noticed it in a year of building OSX... > Would it be sufficient to redirect that warning to /dev/null (as it was done > in the previous code)? The other option would be to just skip the test unless we're building one of the linux-user or bsd-user targets : we'll never build either on OSX. -- PMM
Re: [Qemu-devel] [PATCH v2 01/10] pci: move REDHAT_SDHCI device ID to make room for Rocker
On Wed, Jan 7, 2015 at 2:55 AM, Paolo Bonzini wrote: > > > On 07/01/2015 11:39, Peter Maydell wrote: >>> > Within the virt team, we have always considered the authoritative source >>> > to be qemu.git and Gerd to be the maintainer. Jiri is a Red Hatter but >>> > not in the virt team, hence the confusion. >> OK, so do we: >> (1) say that the authoritative list says this ID is SDHCI, >> so rocker needs to renumber >> (2) as this patch suggests, renumber SDHCI as a one-off fixing >> of an error? > > I already sent a patch for (2) in a pull request. SDHCI was never in a > released version, unlike rocker which was in Linux 3.18, so I don't > think there's even a choice. :) > > I'll send a patch to Linux saying that the authoritative list of device > IDs for 0x1b36 resides in qemu.git. Thanks Paolo. I'll resume the qemu rocker submission process assuming rocker ID stays where it's at and SDHCI is moving. -scott
[Qemu-devel] [PATCH v3 8/8] qemu_ram_resize: document assumptions
Document that when using qemu_ram_resize for anything mapped into guest address space, it's the job of the resize function to update guest visible state. Signed-off-by: Michael S. Tsirkin --- exec.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/exec.c b/exec.c index 71af138..58ac6d6 100644 --- a/exec.c +++ b/exec.c @@ -1301,6 +1301,13 @@ static int memory_try_enable_merging(void *addr, size_t len) return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE); } +/* Only legal before guest might have detected the memory size: e.g. on + * incoming migration, or right after reset. + * + * As memory core doesn't know how is memory accessed, it is up to + * resize callback to update device state and/or add assertions to detect + * misuse, if necessary. + */ int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp) { RAMBlock *block = find_ram_block(base); -- MST
[Qemu-devel] [PATCH v3 7/8] acpi-build: make ROMs RAM blocks resizeable
Use resizeable ram API so we can painlessly extend ROMs in the future. Note: migration is not affected, as we are not actually changing the used length for RAM, which is the part that's migrated. Use this in acpi: reserve x16 more RAM space. Signed-off-by: Michael S. Tsirkin --- hw/lm32/lm32_hwsetup.h | 3 ++- include/hw/loader.h| 4 ++-- hw/core/loader.c | 18 ++ hw/i386/acpi-build.c | 19 ++- 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/hw/lm32/lm32_hwsetup.h b/hw/lm32/lm32_hwsetup.h index 9fd5e69..838754d 100644 --- a/hw/lm32/lm32_hwsetup.h +++ b/hw/lm32/lm32_hwsetup.h @@ -73,7 +73,8 @@ static inline void hwsetup_free(HWSetup *hw) static inline void hwsetup_create_rom(HWSetup *hw, hwaddr base) { -rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE, base, NULL, NULL, NULL); +rom_add_blob("hwsetup", hw->data, TARGET_PAGE_SIZE, + TARGET_PAGE_SIZE, base, NULL, NULL, NULL); } static inline void hwsetup_add_u8(HWSetup *hw, uint8_t u) diff --git a/include/hw/loader.h b/include/hw/loader.h index 6481639..1d76108 100644 --- a/include/hw/loader.h +++ b/include/hw/loader.h @@ -60,7 +60,7 @@ int rom_add_file(const char *file, const char *fw_dir, hwaddr addr, int32_t bootindex, bool option_rom); ram_addr_t rom_add_blob(const char *name, const void *blob, size_t len, - hwaddr addr, const char *fw_file_name, + size_t max_len, hwaddr addr, const char *fw_file_name, FWCfgReadCallback fw_callback, void *callback_opaque); int rom_add_elf_program(const char *name, void *data, size_t datasize, size_t romsize, hwaddr addr); @@ -74,7 +74,7 @@ void do_info_roms(Monitor *mon, const QDict *qdict); #define rom_add_file_fixed(_f, _a, _i) \ rom_add_file(_f, NULL, _a, _i, false) #define rom_add_blob_fixed(_f, _b, _l, _a) \ -rom_add_blob(_f, _b, _l, _a, NULL, NULL, NULL) +rom_add_blob(_f, _b, _l, _l, _a, NULL, NULL, NULL) #define PC_ROM_MIN_VGA 0xc #define PC_ROM_MIN_OPTION 0xc8000 diff --git a/hw/core/loader.c b/hw/core/loader.c index 7527fd3..d3f8501 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -712,12 +712,22 @@ static void rom_insert(Rom *rom) QTAILQ_INSERT_TAIL(&roms, rom, next); } +static void fw_cfg_resized(const char *id, uint64_t length, void *host) +{ +if (fw_cfg) { +fw_cfg_modify_file(fw_cfg, id + strlen("/rom@"), host, length); +} +} + static void *rom_set_mr(Rom *rom, Object *owner, const char *name) { void *data; rom->mr = g_malloc(sizeof(*rom->mr)); -memory_region_init_ram(rom->mr, owner, name, rom->datasize, &error_abort); +memory_region_init_resizeable_ram(rom->mr, owner, name, + rom->datasize, rom->romsize, + fw_cfg_resized, + &error_abort); memory_region_set_readonly(rom->mr, true); vmstate_register_ram_global(rom->mr); @@ -812,7 +822,7 @@ err: } ram_addr_t rom_add_blob(const char *name, const void *blob, size_t len, - hwaddr addr, const char *fw_file_name, + size_t max_len, hwaddr addr, const char *fw_file_name, FWCfgReadCallback fw_callback, void *callback_opaque) { Rom *rom; @@ -821,7 +831,7 @@ ram_addr_t rom_add_blob(const char *name, const void *blob, size_t len, rom = g_malloc0(sizeof(*rom)); rom->name = g_strdup(name); rom->addr = addr; -rom->romsize = len; +rom->romsize = max_len ? max_len : len; rom->datasize = len; rom->data = g_malloc0(rom->datasize); memcpy(rom->data, blob, len); @@ -841,7 +851,7 @@ ram_addr_t rom_add_blob(const char *name, const void *blob, size_t len, fw_cfg_add_file_callback(fw_cfg, fw_file_name, fw_callback, callback_opaque, - data, rom->romsize); + data, rom->datasize); } return ret; } diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index a4d0c0c..6a2e9c5 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -68,6 +68,9 @@ #define ACPI_BUILD_TABLE_SIZE 0x2 +/* Reserve RAM space for tables: add another order of magnitude. */ +#define ACPI_BUILD_TABLE_MAX_SIZE 0x20 + /* #define DEBUG_ACPI_BUILD */ #ifdef DEBUG_ACPI_BUILD #define ACPI_BUILD_DPRINTF(fmt, ...)\ @@ -1718,6 +1721,11 @@ static void acpi_build_update(void *build_opaque, uint32_t offset) acpi_build(build_state->guest_info, &tables); assert(acpi_data_len(tables.table_data) == build_state->table_size); + +/* Make sure RAM size is correct - in case it got changed by migration */ +qemu_ram_resize(build_state->table_ram, build_state->table_size, +
[Qemu-devel] [PATCH v3 6/8] memory: API to allocate resizeable RAM MR
Add API to allocate resizeable RAM MR. This looks just like regular RAM generally, but has a special property that only a portion of it (used_length) is actually used, and migrated. This used_length size can change across reboots. Follow up patches will change used_length for such blocks at migration, making it easier to extend devices using such RAM (notably ACPI, but in the future thinkably other ROMs) without breaking migration compatibility or wasting ROM (guest) memory. Device is notified on resize, so it can adjust if necessary. Note: nothing prevents making all RAM resizeable in this way. However, reviewers felt that only enabling this selectively will make some class of errors easier to detect. Signed-off-by: Michael S. Tsirkin --- include/exec/memory.h | 24 memory.c | 17 + 2 files changed, 41 insertions(+) diff --git a/include/exec/memory.h b/include/exec/memory.h index 0882221..0cd96b1 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -321,6 +321,30 @@ void memory_region_init_ram(MemoryRegion *mr, uint64_t size, Error **errp); +/** + * memory_region_init_resizeable_ram: Initialize memory region with resizeable + * RAM. Accesses into the region will + * modify memory directly. Only an initial + * portion of this RAM is actually used. + * The used size can change across reboots. + * + * @mr: the #MemoryRegion to be initialized. + * @owner: the object that tracks the region's reference count + * @name: the name of the region. + * @size: used size of the region. + * @max_size: max size of the region. + * @resized: callback to notify owner about used size change. + * @errp: pointer to Error*, to store an error if it happens. + */ +void memory_region_init_resizeable_ram(MemoryRegion *mr, + struct Object *owner, + const char *name, + uint64_t size, + uint64_t max_size, + void (*resized)(const char*, + uint64_t length, + void *host), + Error **errp); #ifdef __linux__ /** * memory_region_init_ram_from_file: Initialize RAM memory region with a diff --git a/memory.c b/memory.c index 618470b..c343bf3 100644 --- a/memory.c +++ b/memory.c @@ -1152,6 +1152,23 @@ void memory_region_init_ram(MemoryRegion *mr, mr->ram_addr = qemu_ram_alloc(size, mr, errp); } +void memory_region_init_resizeable_ram(MemoryRegion *mr, + Object *owner, + const char *name, + uint64_t size, + uint64_t max_size, + void (*resized)(const char*, + uint64_t length, + void *host), + Error **errp) +{ +memory_region_init(mr, owner, name, size); +mr->ram = true; +mr->terminates = true; +mr->destructor = memory_region_destructor_ram; +mr->ram_addr = qemu_ram_alloc_resizeable(size, max_size, resized, mr, errp); +} + #ifdef __linux__ void memory_region_init_ram_from_file(MemoryRegion *mr, struct Object *owner, -- MST
[Qemu-devel] [PATCH v3 3/8] exec: split length -> used_length/max_length
This patch allows us to distinguish between two length values for each block: max_length - length of memory block that was allocated used_length - length of block used by QEMU/guest Currently, we set used_length - max_length, unconditionally. Follow-up patches allow used_length <= max_length. Signed-off-by: Michael S. Tsirkin --- include/exec/cpu-all.h | 3 ++- arch_init.c| 19 +- exec.c | 52 +++--- 3 files changed, 40 insertions(+), 34 deletions(-) diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 62f5581..6f2130e 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -303,7 +303,8 @@ typedef struct RAMBlock { struct MemoryRegion *mr; uint8_t *host; ram_addr_t offset; -ram_addr_t length; +ram_addr_t used_length; +ram_addr_t max_length; uint32_t flags; char idstr[256]; /* Reads can take either the iothread or the ramlist lock. diff --git a/arch_init.c b/arch_init.c index 7680d28..106f46e 100644 --- a/arch_init.c +++ b/arch_init.c @@ -522,7 +522,7 @@ static void migration_bitmap_sync(void) address_space_sync_dirty_bitmap(&address_space_memory); QTAILQ_FOREACH(block, &ram_list.blocks, next) { -migration_bitmap_sync_range(block->mr->ram_addr, block->length); +migration_bitmap_sync_range(block->mr->ram_addr, block->used_length); } trace_migration_bitmap_sync_end(migration_dirty_pages - num_dirty_pages_init); @@ -668,7 +668,7 @@ static int ram_find_and_save_block(QEMUFile *f, bool last_stage) offset >= last_offset) { break; } -if (offset >= block->length) { +if (offset >= block->used_length) { offset = 0; block = QTAILQ_NEXT(block, next); if (!block) { @@ -727,7 +727,7 @@ uint64_t ram_bytes_total(void) uint64_t total = 0; QTAILQ_FOREACH(block, &ram_list.blocks, next) -total += block->length; +total += block->used_length; return total; } @@ -831,7 +831,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) QTAILQ_FOREACH(block, &ram_list.blocks, next) { uint64_t block_pages; -block_pages = block->length >> TARGET_PAGE_BITS; +block_pages = block->used_length >> TARGET_PAGE_BITS; migration_dirty_pages += block_pages; } @@ -844,7 +844,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) QTAILQ_FOREACH(block, &ram_list.blocks, next) { qemu_put_byte(f, strlen(block->idstr)); qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr)); -qemu_put_be64(f, block->length); +qemu_put_be64(f, block->used_length); } qemu_mutex_unlock_ramlist(); @@ -1015,7 +1015,7 @@ static inline void *host_from_stream_offset(QEMUFile *f, uint8_t len; if (flags & RAM_SAVE_FLAG_CONTINUE) { -if (!block || block->length <= offset) { +if (!block || block->max_length <= offset) { error_report("Ack, bad migration stream!"); return NULL; } @@ -1028,7 +1028,8 @@ static inline void *host_from_stream_offset(QEMUFile *f, id[len] = 0; QTAILQ_FOREACH(block, &ram_list.blocks, next) { -if (!strncmp(id, block->idstr, sizeof(id)) && block->length > offset) { +if (!strncmp(id, block->idstr, sizeof(id)) && +block->max_length > offset) { return memory_region_get_ram_ptr(block->mr) + offset; } } @@ -1085,10 +1086,10 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (!strncmp(id, block->idstr, sizeof(id))) { -if (block->length != length) { +if (block->used_length != length) { error_report("Length mismatch: %s: 0x" RAM_ADDR_FMT " in != 0x" RAM_ADDR_FMT, id, length, - block->length); + block->used_length); ret = -EINVAL; } break; diff --git a/exec.c b/exec.c index a89aa6c..b69216a 100644 --- a/exec.c +++ b/exec.c @@ -812,11 +812,11 @@ static RAMBlock *qemu_get_ram_block(ram_addr_t addr) /* The list is protected by the iothread lock here. */ block = ram_list.mru_block; -if (block && addr - block->offset < block->length) { +if (block && addr - block->offset < block->max_length) { goto found; } QTAILQ_FOREACH(block, &ram_list.blocks, next) { -if (addr - block->offset < block->length) { +if (addr - block->offset < block->max_length) { goto found; } } @@ -1305,13 +1305,14 @@ static ram_addr_t ram_bloc
[Qemu-devel] [PATCH v3 5/8] arch_init: support resizing on incoming migration
If block used_length does not match, try to resize it. Signed-off-by: Michael S. Tsirkin --- arch_init.c | 13 - 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/arch_init.c b/arch_init.c index 106f46e..cfedbf0 100644 --- a/arch_init.c +++ b/arch_init.c @@ -1086,11 +1086,14 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) QTAILQ_FOREACH(block, &ram_list.blocks, next) { if (!strncmp(id, block->idstr, sizeof(id))) { -if (block->used_length != length) { -error_report("Length mismatch: %s: 0x" RAM_ADDR_FMT - " in != 0x" RAM_ADDR_FMT, id, length, - block->used_length); -ret = -EINVAL; +if (length != block->used_length) { +Error *local_err = NULL; + +ret = qemu_ram_resize(block->offset, length, &local_err); +if (local_err) { +error_report("%s", error_get_pretty(local_err)); +error_free(local_err); +} } break; } -- MST
[Qemu-devel] [PATCH v3 4/8] exec: qemu_ram_alloc_resizeable, qemu_ram_resize
Add API to allocate "resizeable" RAM. This looks just like regular RAM generally, but has a special property that only a portion of it (used_length) is actually used, and migrated. This used_length size can change across reboots. Follow up patches will change used_length for such blocks at migration, making it easier to extend devices using such RAM (notably ACPI, but in the future thinkably other ROMs) without breaking migration compatibility or wasting ROM (guest) memory. Device is notified on resize, so it can adjust if necessary. qemu_ram_alloc_resizeable allocates this memory, qemu_ram_resize resizes it. Note: nothing prevents making all RAM resizeable in this way. However, reviewers felt that only enabling this selectively will make some class of errors easier to detect. Signed-off-by: Michael S. Tsirkin --- include/exec/cpu-all.h | 9 -- include/exec/ram_addr.h | 7 + exec.c | 75 ++--- 3 files changed, 84 insertions(+), 7 deletions(-) diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 6f2130e..7ced147 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -299,12 +299,15 @@ CPUArchState *cpu_copy(CPUArchState *env); /* memory API */ -typedef struct RAMBlock { +typedef struct RAMBlock RAMBlock; + +struct RAMBlock { struct MemoryRegion *mr; uint8_t *host; ram_addr_t offset; ram_addr_t used_length; ram_addr_t max_length; +void (*resized)(const char*, uint64_t length, void *host); uint32_t flags; char idstr[256]; /* Reads can take either the iothread or the ramlist lock. @@ -312,11 +315,11 @@ typedef struct RAMBlock { */ QTAILQ_ENTRY(RAMBlock) next; int fd; -} RAMBlock; +}; static inline void *ramblock_ptr(RAMBlock *block, ram_addr_t offset) { -assert(offset < block->length); +assert(offset < block->used_length); assert(block->host); return (char *)block->host + offset; } diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 254931c..ff558a4 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -28,12 +28,19 @@ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr, Error **errp); ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr, Error **errp); +ram_addr_t qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t max_size, + void (*resized)(const char*, + uint64_t length, + void *host), + MemoryRegion *mr, Error **errp); int qemu_get_ram_fd(ram_addr_t addr); void *qemu_get_ram_block_host_ptr(ram_addr_t addr); void *qemu_get_ram_ptr(ram_addr_t addr); void qemu_ram_free(ram_addr_t addr); void qemu_ram_free_from_ptr(ram_addr_t addr); +int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp); + static inline bool cpu_physical_memory_get_dirty(ram_addr_t start, ram_addr_t length, unsigned client) diff --git a/exec.c b/exec.c index b69216a..71af138 100644 --- a/exec.c +++ b/exec.c @@ -75,6 +75,11 @@ static MemoryRegion io_mem_unassigned; /* RAM is mmap-ed with MAP_SHARED */ #define RAM_SHARED (1 << 1) +/* Only a portion of RAM (used_length) is actually used, and migrated. + * This used_length size can change across reboots. + */ +#define RAM_RESIZEABLE (1 << 2) + #endif struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus); @@ -1186,7 +1191,7 @@ static ram_addr_t find_ram_offset(ram_addr_t size) QTAILQ_FOREACH(block, &ram_list.blocks, next) { ram_addr_t end, next = RAM_ADDR_MAX; -end = block->offset + block->length; +end = block->offset + block->max_length; QTAILQ_FOREACH(next_block, &ram_list.blocks, next) { if (next_block->offset >= end) { @@ -1214,7 +1219,7 @@ ram_addr_t last_ram_offset(void) ram_addr_t last = 0; QTAILQ_FOREACH(block, &ram_list.blocks, next) -last = MAX(last, block->offset + block->length); +last = MAX(last, block->offset + block->max_length); return last; } @@ -1296,6 +1301,42 @@ static int memory_try_enable_merging(void *addr, size_t len) return qemu_madvise(addr, len, QEMU_MADV_MERGEABLE); } +int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp) +{ +RAMBlock *block = find_ram_block(base); + +assert(block); + +if (block->used_length == newsize) { +return 0; +} + +if (!(block->flags & RAM_RESIZEABLE)) { +error_setg_errno(errp, EINVAL, + "Length mismatch: %s: 0x" RAM_ADDR_FMT + " in != 0x" RAM_ADDR_FMT, block->idstr, +
[Qemu-devel] [PATCH v3 0/8] acpi: make ROMs resizeable
This is v3 of the patchset. Changes since v2: - Address Paolo's comments: drop an unused function, fix up comment. Changes since v1: - Any RAM can now be resizeable - there's no requirement that it's device RAM any longer. - For simplicity, max_size RAM is always pre-allocated - Added memory_region_set_size, to keep MR size consistent in case MR is guest visible (even though for current users, it never is) At the moment we migrate ROMs which reside in fw cfg, which allows changing ROM code at will, and supports migrating largish blocks early, with good performance. However, we are running into a problem: changing size breaks migration every time. This already requires somewhat messy compatibility support in acpi generation code, and it looks like there'll be more to come. While recent patches by Paolo and others might make it easier to keep table size static for specific machine types, having a safety net in case we do need to change it sounds like a good idea. Rather than try to guess the correct size once and for all, this patchset tries to make code future-proof, by adding support for resizeable ram blocks. A (possibly very high) amount of space in ram_addr_t space is reserved and allocated in host for each block, but never used by fw cfg. If incoming block size differs from current size, block is reallocated. FW CFG is also notified and updated accordingly. As reviewers felt that making all RAM "resizeable" in this way might make debugging migration harder, these patches set a per-block flag and only allow resizing for blocks where this was explicitly requested. Note: migration stream is unaffected by these patches. This makes it possible to enable this functionality unconditionally, for all machine types. In the future, this API might be handy for other things, besides ROMs. Michael S. Tsirkin (8): memory: add memory_region_set_size exec: cpu_physical_memory_set/clear_dirty_range exec: split length -> used_length/max_length exec: qemu_ram_alloc_resizeable, qemu_ram_resize arch_init: support resizing on incoming migration memory: API to allocate resizeable RAM MR acpi-build: make ROMs RAM blocks resizeable qemu_ram_resize: document assumptions hw/lm32/lm32_hwsetup.h | 3 +- include/exec/cpu-all.h | 12 +++-- include/exec/memory.h | 34 include/exec/ram_addr.h | 22 ++-- include/hw/loader.h | 4 +- arch_init.c | 28 +- exec.c | 136 +--- hw/core/loader.c| 18 +-- hw/i386/acpi-build.c| 19 +-- memory.c| 33 10 files changed, 249 insertions(+), 60 deletions(-) -- MST
[Qemu-devel] [PATCH v3 1/8] memory: add memory_region_set_size
Add API to change MR size. Will be used internally for RAM resize. Signed-off-by: Michael S. Tsirkin --- include/exec/memory.h | 10 ++ memory.c | 16 2 files changed, 26 insertions(+) diff --git a/include/exec/memory.h b/include/exec/memory.h index f64ab5e..0882221 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -878,6 +878,16 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled); void memory_region_set_address(MemoryRegion *mr, hwaddr addr); /* + * memory_region_set_size: dynamically update the size of a region. + * + * Dynamically updates the size of a region. + * + * @mr: the region to be updated + * @size: used size of the region. + */ +void memory_region_set_size(MemoryRegion *mr, uint64_t size); + +/* * memory_region_set_alias_offset: dynamically update a memory alias's offset * * Dynamically updates the offset into the target region that an alias points diff --git a/memory.c b/memory.c index 15cf9eb..618470b 100644 --- a/memory.c +++ b/memory.c @@ -1707,6 +1707,22 @@ void memory_region_set_enabled(MemoryRegion *mr, bool enabled) memory_region_transaction_commit(); } +void memory_region_set_size(MemoryRegion *mr, uint64_t size) +{ +Int128 s = int128_make64(size); + +if (size == UINT64_MAX) { +s = int128_2_64(); +} +if (int128_eq(s, mr->size)) { +return; +} +memory_region_transaction_begin(); +mr->size = s; +memory_region_update_pending = true; +memory_region_transaction_commit(); +} + static void memory_region_readd_subregion(MemoryRegion *mr) { MemoryRegion *container = mr->container; -- MST
[Qemu-devel] [PATCH v3 2/8] exec: cpu_physical_memory_set/clear_dirty_range
Make cpu_physical_memory_set/clear_dirty_range behave symmetrically. To clear range for a given client type only, add cpu_physical_memory_clear_dirty_range_type. Signed-off-by: Michael S. Tsirkin --- include/exec/ram_addr.h | 15 --- exec.c | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 8fc75cd..254931c 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -172,9 +172,9 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap, } #endif /* not _WIN32 */ -static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, - ram_addr_t length, - unsigned client) +static inline void cpu_physical_memory_clear_dirty_range_type(ram_addr_t start, + ram_addr_t length, + unsigned client) { unsigned long end, page; @@ -184,6 +184,15 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, bitmap_clear(ram_list.dirty_memory[client], page, end - page); } +static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, + ram_addr_t length) +{ +cpu_physical_memory_clear_dirty_range_type(start, length, DIRTY_MEMORY_MIGRATION); +cpu_physical_memory_clear_dirty_range_type(start, length, DIRTY_MEMORY_VGA); +cpu_physical_memory_clear_dirty_range_type(start, length, DIRTY_MEMORY_CODE); +} + + void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length, unsigned client); diff --git a/exec.c b/exec.c index 963481a..a89aa6c 100644 --- a/exec.c +++ b/exec.c @@ -850,7 +850,7 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length, { if (length == 0) return; -cpu_physical_memory_clear_dirty_range(start, length, client); +cpu_physical_memory_clear_dirty_range_type(start, length, client); if (tcg_enabled()) { tlb_reset_dirty_range_all(start, length); -- MST
Re: [Qemu-devel] [PATCH RFC v6 19/20] virtio-blk: revision specific feature bits
On Wed, Jan 07, 2015 at 05:29:49PM +0100, Cornelia Huck wrote: > On Sun, 28 Dec 2014 12:24:46 +0200 > "Michael S. Tsirkin" wrote: > > > On Thu, Dec 11, 2014 at 02:25:21PM +0100, Cornelia Huck wrote: > > > Wire up virtio-blk to provide different feature bit sets depending > > > on whether legacy or v1.0 has been requested. > > > > > > Note that VERSION_1 is still disabled due to missing ANY_LAYOUT support. > > > > > > Signed-off-by: Cornelia Huck > > > > So we need some way for devices to tell transports > > not to negotiate rev 1. > > Does clearing VERSION_1 have this effect? > > > I just noticed that my patch is running in circles here. > > What we need is probably the transport-dependent maximum revision > checker (which at least for ccw is acting on a device) pass in the > requested revision and check if the feature bits for the revision > include VERSION_1. Does that make sense? Just make devices set 'rev 1 supported' flag?
Re: [Qemu-devel] [PATCH RFC v6 18/20] virtio: support revision-specific features
On Wed, Jan 07, 2015 at 05:22:32PM +0100, Cornelia Huck wrote: > On Sun, 28 Dec 2014 10:32:06 +0200 > "Michael S. Tsirkin" wrote: > > > On Thu, Dec 11, 2014 at 02:25:20PM +0100, Cornelia Huck wrote: > > > Devices may support different sets of feature bits depending on which > > > revision they're operating at. Let's give the transport a way to > > > re-query the device about its features when the revision has been > > > changed. > > > > > > Signed-off-by: Cornelia Huck > > > > So now we have both get_features and get_features_rev, and > > it's never clear which revision does host_features refer to. > > IMHO that's just too messy. > > Let's add get_legacy_features and host_legacy_features instead? > > I wanted to avoid touching anything that does not support version 1. > And this interface might still work for later revisions, no? We can add _modern_ then, or rename host_features to host_legacy_features everywhere as preparation. -- MST
Re: [Qemu-devel] [PATCH RFC v6 13/20] virtio: allow to fail setting status
On Wed, Jan 07, 2015 at 05:13:32PM +0100, Cornelia Huck wrote: > On Tue, 30 Dec 2014 14:25:37 +0200 > "Michael S. Tsirkin" wrote: > > > On Thu, Dec 11, 2014 at 02:25:15PM +0100, Cornelia Huck wrote: > > > virtio-1 allow setting of the FEATURES_OK status bit to fail if > > > the negotiated feature bits are inconsistent: let's fail > > > virtio_set_status() in that case and update virtio-ccw to post an > > > error to the guest. > > > > > > Signed-off-by: Cornelia Huck > > > > Right but a separate validate_features call is awkward. > > How about we defer virtio_set_features until FEATURES_OK, > > and teach virtio_set_features that it can fail? > > Hm. But we would need to keep virtio_set_features() where it is called > now for legacy devices, as they will never see FEATURES_OK, right? > So > we need to make this depending on revisions (or whatever the equivalent > is for pci/mmio), as we cannot check for VERSION_1. Not sure whether > this makes the code easier to follow. So let's make this a separate callback then. virtio_legacy_set_features?
Re: [Qemu-devel] [PATCH v3] configure: Simplify alternate .text segment
On 01/07/2015 10:02 AM, Stefan Weil wrote: > Would it be sufficient to redirect that warning to /dev/null (as it was done > in > the previous code)? Probably. r~
Re: [Qemu-devel] [PATCH v2 09/12] block/dmg: use SectorNumber from BLKX header
On 01/06/2015 12:48 PM, Peter Wu wrote: Previously the sector table parsing relied on the previous offset of the DMG file. Now it uses the sector number from the BLKX header (see http://newosxbook.com/DMG.html). The implementation of dmg2img (from vu1tur) does not base the output sector on the location of the terminator (0x) either so it should be safe to drop this dependency on the previous state. (It makes somehow makes sense, a terminator should halt further processing of a block and is perhaps used to preallocate some space.) Signed-off-by: Peter Wu --- v2: initial patch after suggestions from John Snow to read and use these fields. --- block/dmg.c | 12 +--- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/block/dmg.c b/block/dmg.c index 130efac..57922c5 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -189,7 +189,6 @@ typedef struct DmgHeaderState { /* used internally by dmg_read_mish_block to remember offsets of blocks * across calls */ uint64_t data_fork_offset; -uint64_t last_out_offset; /* exported for dmg_open */ uint32_t max_compressed_size; uint32_t max_sectors_per_chunk; @@ -205,6 +204,7 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, int64_t offset = 0; uint64_t data_offset; uint64_t in_offset = ds->data_fork_offset; +uint64_t out_offset; type = buff_read_uint32(buffer, offset); /* skip data that is not a valid MISH block (invalid magic or too small) */ @@ -213,6 +213,9 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, return 0; } +/* chunk offsets are relative to this sector number */ +out_offset = buff_read_uint64(buffer, offset + 8); + /* location in data fork for (compressed) blob (in bytes) */ data_offset = buff_read_uint64(buffer, offset + 0x18); in_offset += data_offset; @@ -233,10 +236,6 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, offset += 4; if (s->types[i] != 0x8005 && s->types[i] != 1 && s->types[i] != 2) { -if (s->types[i] == 0x && i > 0) { -ds->last_out_offset = s->sectors[i - 1] + - s->sectorcounts[i - 1]; -} This is exactly what I was hoping to see could be eliminated by reading the mish headers. Thanks for this. chunk_count--; i--; offset += 36; @@ -245,7 +244,7 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, offset += 4; s->sectors[i] = buff_read_uint64(buffer, offset); -s->sectors[i] += ds->last_out_offset; +s->sectors[i] += out_offset; offset += 8; s->sectorcounts[i] = buff_read_uint64(buffer, offset); @@ -419,7 +418,6 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL; /* used by dmg_read_mish_block to keep track of the current I/O position */ ds.data_fork_offset = 0; -ds.last_out_offset = 0; ds.max_compressed_size = 1; ds.max_sectors_per_chunk = 1; Much nicer. Reviewed-by: John Snow
Re: [Qemu-devel] [PATCH v2 12/12] block/dmg: improve zeroes handling
On 01/06/2015 12:48 PM, Peter Wu wrote: Disk images may contain large all-zeroes gaps (1.66k sectors or 812 MiB is seen in the real world). These blocks (type 2) do not need to be extracted into a temporary buffer, there is no need to allocate memory for these blocks nor to check its length. (For the test image, the maximum uncompressed size is 1054371 bytes, probably for a bzip2-compressed block.) Signed-off-by: Peter Wu --- v2: no changes (did not receive comments last time) --- block/dmg.c | 18 +++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/block/dmg.c b/block/dmg.c index 8239221..4e24076 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -137,7 +137,9 @@ static void update_max_chunk_size(BDRVDMGState *s, uint32_t chunk, uncompressed_sectors = (s->lengths[chunk] + 511) / 512; break; case 2: /* zero */ -uncompressed_sectors = s->sectorcounts[chunk]; +/* as the all-zeroes block may be large, it is treated specially: the + * sector is not copied from a large buffer, a simple memset is used + * instead. Therefore uncompressed_sectors does not need to be set. */ break; } @@ -269,7 +271,9 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, /* sector count */ s->sectorcounts[i] = buff_read_uint64(buffer, offset + 0x10); -if (s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) { +/* all-zeroes sector (type 2) does not need to be "uncompressed" and can + * therefore be unbounded. */ +if (s->types[i] != 2 && s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) { error_report("sector count %" PRIu64 " for chunk %" PRIu32 " is larger than max (%u)", s->sectorcounts[i], i, DMG_SECTORCOUNTS_MAX); @@ -644,7 +648,8 @@ static inline int dmg_read_chunk(BlockDriverState *bs, uint64_t sector_num) } break; case 2: /* zero */ -memset(s->uncompressed_chunk, 0, 512 * s->sectorcounts[chunk]); +/* see dmg_read, it is treated specially. No buffer needs to be + * pre-filled, the zeroes can be set directly. */ break; } s->current_chunk = chunk; @@ -663,6 +668,13 @@ static int dmg_read(BlockDriverState *bs, int64_t sector_num, if (dmg_read_chunk(bs, sector_num + i) != 0) { return -1; } +/* Special case: current chunk is all zeroes. Do not perform a memcpy as + * s->uncompressed_chunk may be too small to cover the large all-zeroes + * section. dmg_read_chunk is called to find s->current_chunk */ +if (s->types[s->current_chunk] == 2) { /* all zeroes block entry */ +memset(buf + i * 512, 0, 512); +continue; +} sector_offset_in_chunk = sector_num + i - s->sectors[s->current_chunk]; memcpy(buf + i * 512, s->uncompressed_chunk + sector_offset_in_chunk * 512, 512); Reviewed-by: John Snow
Re: [Qemu-devel] [PATCH v2 11/12] block/dmg: support bzip2 block entry types
On 01/06/2015 12:48 PM, Peter Wu wrote: This patch adds support for bzip2-compressed block entries as introduced with OS X 10.4 (source: https://en.wikipedia.org/wiki/Apple_Disk_Image). It was tested against a 5.2G "OS X Yosemite" installation image which stores the BLXX block in the XML property list (instead of resource forks) and has over 5k chunks. New configure entries are added (--enable-bzip2 / --disable-bzip2) to control inclusion of bzip2 functionality (which requires linking against libbz2). The help message suggests that this option is needed for DMG files, but the tests are generic enough that other parts of QEMU can use bzip2 if needed. The identifiers are based on http://newosxbook.com/DMG.html. The decompression routines are based on the zlib case, but as there is no way to reset the decompression state (unlike zlib), memory is allocated and deallocated for every decompression. This should not be problematic as the decompression takes most of the time and as blocks are typically about/over 1 MiB in size, only one allocation is done every 2000 sectors. Signed-off-by: Peter Wu --- v2: split block type check into a different patch ("[PATCH v2 10/12] block/dmg: factor out block type check"). Add BZIP2_LIBS instead of polluting libs_softmmu with -lbz2 (which would also end up in fsdev/virtfs-proxy-helper). Fix unused variable warning with --disable-bzip2. --- block/Makefile.objs | 1 + block/dmg.c | 43 ++- configure | 31 +++ 3 files changed, 74 insertions(+), 1 deletion(-) [snip] Reviewed-by: John Snow
Re: [Qemu-devel] [PATCH v2 10/12] block/dmg: factor out block type check
On 01/06/2015 12:48 PM, Peter Wu wrote: In preparation for adding bzip2 support, split the type check into a separate function. Make all offsets relative to the begin of a chunk such that it is easier to recognize the position without having to add up all offsets. Some comments are added to describe the fields. There is no functional change. Signed-off-by: Peter Wu --- v2: new patch, split off bzip2 patch. Besides the dmg_is_known_block_type function, the offsets are now also made relative. --- block/dmg.c | 36 +++- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/block/dmg.c b/block/dmg.c index 57922c5..b1d0930 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -194,6 +194,18 @@ typedef struct DmgHeaderState { uint32_t max_sectors_per_chunk; } DmgHeaderState; +static bool dmg_is_known_block_type(uint32_t entry_type) +{ +switch (entry_type) { +case 0x0001:/* uncompressed */ +case 0x0002:/* zeroes */ +case 0x8005:/* zlib */ +return true; +default: +return false; +} +} + static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, uint8_t *buffer, uint32_t count) { @@ -233,22 +245,19 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, for (i = s->n_chunks; i < s->n_chunks + chunk_count; i++) { s->types[i] = buff_read_uint32(buffer, offset); -offset += 4; -if (s->types[i] != 0x8005 && s->types[i] != 1 && -s->types[i] != 2) { +if (!dmg_is_known_block_type(s->types[i])) { chunk_count--; i--; -offset += 36; +offset += 40; continue; } -offset += 4; -s->sectors[i] = buff_read_uint64(buffer, offset); +/* sector number */ +s->sectors[i] = buff_read_uint64(buffer, offset + 8); s->sectors[i] += out_offset; -offset += 8; -s->sectorcounts[i] = buff_read_uint64(buffer, offset); -offset += 8; +/* sector count */ +s->sectorcounts[i] = buff_read_uint64(buffer, offset + 0x10); if (s->sectorcounts[i] > DMG_SECTORCOUNTS_MAX) { error_report("sector count %" PRIu64 " for chunk %" PRIu32 @@ -258,12 +267,12 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, goto fail; } -s->offsets[i] = buff_read_uint64(buffer, offset); +/* offset in (compressed) data fork */ +s->offsets[i] = buff_read_uint64(buffer, offset + 0x18); s->offsets[i] += in_offset; -offset += 8; -s->lengths[i] = buff_read_uint64(buffer, offset); -offset += 8; +/* length in (compressed) data fork */ +s->lengths[i] = buff_read_uint64(buffer, offset + 0x20); if (s->lengths[i] > DMG_LENGTHS_MAX) { error_report("length %" PRIu64 " for chunk %" PRIu32 @@ -275,6 +284,7 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, update_max_chunk_size(s, i, &ds->max_compressed_size, &ds->max_sectors_per_chunk); +offset += 40; } s->n_chunks += chunk_count; return 0; Reviewed-by: John Snow
Re: [Qemu-devel] [PATCH v2 08/12] block/dmg: fix sector data offset calculation
On 01/06/2015 12:48 PM, Peter Wu wrote: This patch addresses two issues: - The data fork offset was not taken into account, resulting in failure to read an InstallESD.dmg file (5164763151 bytes) which had a non-zero DataForkOffset field. - The offset of the previous block ("partition") was unconditionally added to the current block because older files would start the input offset of a new block at zero. Newer files (including vlc-2.1.5.dmg, tuxpaint-0.9.15-macosx.dmg and OS X Yosemite [MAS].dmg) failed in reads because these files have chunk offsets, relative to the begin of a data fork. Now the data offset of the mish is taken into account. While we could check that the data_offset is within the data fork, let's not do that here as it would only result in parse failures on invalid files (rather than gracefully handling such bad files). dmg_read will error out if the offset is incorrect. Signed-off-by: Peter Wu --- v2: use sector and data offset as provided by the BLKX header. This allows us to drop last_in_offset. The previous heuristics to detect relative offsets is not needed anymore. Squashed the data fork offset length check into this patch. --- block/dmg.c | 26 -- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/block/dmg.c b/block/dmg.c index 57feb1b..130efac 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -188,7 +188,7 @@ static int64_t dmg_find_koly_offset(BlockDriverState *file_bs, Error **errp) typedef struct DmgHeaderState { /* used internally by dmg_read_mish_block to remember offsets of blocks * across calls */ -uint64_t last_in_offset; +uint64_t data_fork_offset; uint64_t last_out_offset; /* exported for dmg_open */ uint32_t max_compressed_size; @@ -203,6 +203,8 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, size_t new_size; uint32_t chunk_count; int64_t offset = 0; +uint64_t data_offset; +uint64_t in_offset = ds->data_fork_offset; type = buff_read_uint32(buffer, offset); /* skip data that is not a valid MISH block (invalid magic or too small) */ @@ -211,8 +213,12 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, return 0; } -offset += 4; -offset += 200; +/* location in data fork for (compressed) blob (in bytes) */ +data_offset = buff_read_uint64(buffer, offset + 0x18); +in_offset += data_offset; + +/* move to begin of chunk entries */ +offset += 204; chunk_count = (count - 204) / 40; new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count); @@ -228,7 +234,6 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, if (s->types[i] != 0x8005 && s->types[i] != 1 && s->types[i] != 2) { if (s->types[i] == 0x && i > 0) { -ds->last_in_offset = s->offsets[i - 1] + s->lengths[i - 1]; Great! ds->last_out_offset = s->sectors[i - 1] + s->sectorcounts[i - 1]; } @@ -255,7 +260,7 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, } s->offsets[i] = buff_read_uint64(buffer, offset); -s->offsets[i] += ds->last_in_offset; +s->offsets[i] += in_offset; offset += 8; s->lengths[i] = buff_read_uint64(buffer, offset); @@ -413,7 +418,7 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, s->n_chunks = 0; s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL; /* used by dmg_read_mish_block to keep track of the current I/O position */ -ds.last_in_offset = 0; +ds.data_fork_offset = 0; ds.last_out_offset = 0; ds.max_compressed_size = 1; ds.max_sectors_per_chunk = 1; @@ -425,6 +430,15 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, goto fail; } +/* offset of data fork (DataForkOffset) */ +ret = read_uint64(bs, offset + 0x18, &ds.data_fork_offset); +if (ret < 0) { +goto fail; +} else if (ds.data_fork_offset > offset) { +ret = -EINVAL; +goto fail; +} + /* offset of resource fork (RsrcForkOffset) */ ret = read_uint64(bs, offset + 0x28, &rsrc_fork_offset); if (ret < 0) { Reviewed-by: John Snow
Re: [Qemu-devel] [PATCH v2 07/12] block/dmg: set virtual size to a non-zero value
On 01/06/2015 12:48 PM, Peter Wu wrote: Right now the virtual size is always reported as zero which makes it impossible to convert between formats. After this patch, the number of sectors will be read from the trailer ("koly" block). To verify the behavior, the output of `dmg2img foo.dmg foo.img` was compared against `qemu-img convert -f dmg -O raw foo.dmg foo.raw`. The tests showed that the file contents are exactly the same, except that QEMU creates a slightly larger file (it matches the total sectors count). Signed-off-by: Peter Wu --- v2: fixed typo in commit message (s/mish/koly/) --- block/dmg.c | 8 1 file changed, 8 insertions(+) diff --git a/block/dmg.c b/block/dmg.c index 1a0fa0e..57feb1b 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -453,6 +453,14 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, ret = -EINVAL; goto fail; } +ret = read_uint64(bs, offset + 0x1ec, (uint64_t *)&bs->total_sectors); +if (ret < 0) { +goto fail; +} +if (bs->total_sectors < 0) { +ret = -EINVAL; +goto fail; +} if (rsrc_fork_length != 0) { ret = dmg_read_resource_fork(bs, &ds, rsrc_fork_offset, rsrc_fork_length); You may want to adjust the commit message here to reflect the information in your new cover letter regarding the bug in dmg2img, but that's not worth re-spinning for. Reviewed-by: John Snow
Re: [Qemu-devel] [PATCH v2 06/12] block/dmg: process XML plists
On 01/06/2015 12:48 PM, Peter Wu wrote: The format is simple enough to avoid using a full-blown XML parser. It assumes that all BLKX items begin with the "mish" magic word, therefore it is not a problem if other values get matched which are not a BLKX block. The offsets are based on the description at http://newosxbook.com/DMG.html Signed-off-by: Peter Wu --- v2: added offset check, allow resource fork to be located at beginning of file (removed `rsrc_fork_offset != 0` condition) It got a `Reviewed-by: John Snow ` for v1. I have not copied the R-b as I wanted to be sure that John agrees with the removal of the offset != 0 condition. It makes sense to me, but as I don't really have an authoritative standard to follow, this really relies on "This didn't break anything obvious." I think you have more images than I do, and as long as you tested them again under v2: Reviewed-by: John Snow --- block/dmg.c | 74 + 1 file changed, 74 insertions(+) diff --git a/block/dmg.c b/block/dmg.c index 5f6976b..1a0fa0e 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -26,6 +26,7 @@ #include "qemu/bswap.h" #include "qemu/module.h" #include +#include enum { /* Limit chunk sizes to prevent unreasonable amounts of memory being used @@ -345,12 +346,66 @@ fail: return ret; } +static int dmg_read_plist_xml(BlockDriverState *bs, DmgHeaderState *ds, + uint64_t info_begin, uint64_t info_length) +{ +BDRVDMGState *s = bs->opaque; +int ret; +uint8_t *buffer = NULL; +char *data_begin, *data_end; + +/* Have at least some length to avoid NULL for g_malloc. Attempt to set a + * safe upper cap on the data length. A test sample had a XML length of + * about 1 MiB. */ +if (info_length == 0 || info_length > 16 * 1024 * 1024) { +ret = -EINVAL; +goto fail; +} + +buffer = g_malloc(info_length + 1); +buffer[info_length] = '\0'; +ret = bdrv_pread(bs->file, info_begin, buffer, info_length); +if (ret != info_length) { +ret = -EINVAL; +goto fail; +} + +/* look for The data is 284 (0x11c) bytes after base64 + * decode. The actual data element has 431 (0x1af) bytes which includes tabs + * and line feeds. */ +data_end = (char *)buffer; +while ((data_begin = strstr(data_end, "")) != NULL) { +gsize out_len = 0; + +data_begin += 6; +data_end = strstr(data_begin, ""); +/* malformed XML? */ +if (data_end == NULL) { +ret = -EINVAL; +goto fail; +} +*data_end++ = '\0'; +g_base64_decode_inplace(data_begin, &out_len); +ret = dmg_read_mish_block(s, ds, (uint8_t *)data_begin, + (uint32_t)out_len); +if (ret < 0) { +goto fail; +} +} +ret = 0; + +fail: +g_free(buffer); +return ret; +} + static int dmg_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVDMGState *s = bs->opaque; DmgHeaderState ds; uint64_t rsrc_fork_offset, rsrc_fork_length; +uint64_t plist_xml_offset, plist_xml_length; int64_t offset; int ret; @@ -384,12 +439,31 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, ret = -EINVAL; goto fail; } +/* offset of property list (XMLOffset) */ +ret = read_uint64(bs, offset + 0xd8, &plist_xml_offset); +if (ret < 0) { +goto fail; +} +ret = read_uint64(bs, offset + 0xe0, &plist_xml_length); +if (ret < 0) { +goto fail; +} +if (plist_xml_offset >= offset || +plist_xml_length > offset - plist_xml_offset) { +ret = -EINVAL; +goto fail; +} if (rsrc_fork_length != 0) { ret = dmg_read_resource_fork(bs, &ds, rsrc_fork_offset, rsrc_fork_length); if (ret < 0) { goto fail; } +} else if (plist_xml_length != 0) { +ret = dmg_read_plist_xml(bs, &ds, plist_xml_offset, plist_xml_length); +if (ret < 0) { +goto fail; +} } else { ret = -EINVAL; goto fail;
Re: [Qemu-devel] [PATCH v2 03/12] block/dmg: extract processing of resource forks
On 01/06/2015 12:48 PM, Peter Wu wrote: Besides the offset, also read the resource length. This length is now used in the extracted function to verify the end of the resource fork against "count" from the resource fork. Instead of relying on the value of offset to conclude whether the resource fork is available or not (info_begin==0), check the rsrc_fork_length instead. This would allow a dmg file to begin with a resource fork. This seemingly unnecessary restriction was found while trying to craft a DMG file by hand. Other changes: - Do not require resource data offset to be 0x100 (but check that it is within bounds though). - Further improve boundary checking (resource data must be within the resource fork). - Use correct value for resource data length (spotted by John Snow) - Consider the resource data offset when determining info_end. This fixes an EINVAL on the tuxpaint dmg example. The resource fork format is documented at https://developer.apple.com/legacy/library/documentation/mac/pdf/MoreMacintoshToolbox.pdf#page=151 Signed-off-by: Peter Wu --- v2: expanded commit message (incl. documentation link). Do not require a fixed resource data offset of 0x100, improve boundary checking, fix resource data len (8 vs 4), append offset when checking the end of the resource data. -- block/dmg.c | 104 ++-- 1 file changed, 66 insertions(+), 38 deletions(-) diff --git a/block/dmg.c b/block/dmg.c index e01559f..ed99cf5 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -287,60 +287,38 @@ fail: return ret; } -static int dmg_open(BlockDriverState *bs, QDict *options, int flags, -Error **errp) +static int dmg_read_resource_fork(BlockDriverState *bs, DmgHeaderState *ds, + uint64_t info_begin, uint64_t info_length) { -BDRVDMGState *s = bs->opaque; -DmgHeaderState ds; -uint64_t info_begin, info_end; -uint32_t count, rsrc_data_offset; -int64_t offset; int ret; +uint32_t count, rsrc_data_offset; +uint64_t info_end; +uint64_t offset; -bs->read_only = 1; -s->n_chunks = 0; -s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL; -/* used by dmg_read_mish_block to keep track of the current I/O position */ -ds.last_in_offset = 0; -ds.last_out_offset = 0; -ds.max_compressed_size = 1; -ds.max_sectors_per_chunk = 1; - -/* locate the UDIF trailer */ -offset = dmg_find_koly_offset(bs->file, errp); -if (offset < 0) { -ret = offset; -goto fail; -} - -ret = read_uint64(bs, offset + 0x28, &info_begin); -if (ret < 0) { -goto fail; -} else if (info_begin == 0) { -ret = -EINVAL; -goto fail; -} - +/* read offset from begin of resource fork (info_begin) to resource data */ ret = read_uint32(bs, info_begin, &rsrc_data_offset); if (ret < 0) { goto fail; -} else if (rsrc_data_offset != 0x100) { +} else if (rsrc_data_offset > info_length) { ret = -EINVAL; goto fail; } -ret = read_uint32(bs, info_begin + 4, &count); +/* read length of resource data */ +ret = read_uint32(bs, info_begin + 8, &count); if (ret < 0) { goto fail; -} else if (count == 0) { +} else if (count == 0 || rsrc_data_offset + count > info_length) { ret = -EINVAL; goto fail; } -/* end of resource data, ignoring the following resource map */ -info_end = info_begin + count; /* begin of resource data (consisting of one or more resources) */ -offset = info_begin + 0x100; +offset = info_begin + rsrc_data_offset; + +/* end of resource data (there is possibly a following resource map + * which will be ignored). */ +info_end = offset + count; /* read offsets (mish blocks) from one or more resources in resource data */ while (offset < info_end) { @@ -354,13 +332,63 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, } offset += 4; -ret = dmg_read_mish_block(bs, &ds, offset, count); +ret = dmg_read_mish_block(bs, ds, offset, count); if (ret < 0) { goto fail; } /* advance offset by size of resource */ offset += count; } +return 0; + +fail: +return ret; +} + +static int dmg_open(BlockDriverState *bs, QDict *options, int flags, +Error **errp) +{ +BDRVDMGState *s = bs->opaque; +DmgHeaderState ds; +uint64_t rsrc_fork_offset, rsrc_fork_length; +int64_t offset; +int ret; + +bs->read_only = 1; +s->n_chunks = 0; +s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL; +/* used by dmg_read_mish_block to keep track of the current I/O position */ +ds.last_in_offset = 0; +ds.last_out_offset = 0; +ds.max_compressed_size = 1
Re: [Qemu-devel] [PATCH v2 05/12] block/dmg: validate chunk size to avoid overflow
On 01/06/2015 12:48 PM, Peter Wu wrote: Previously the chunk size was not checked, allowing for a large memory allocation. This patch checks whether the chunks size is within the resource fork length, and whether the resource fork is below the trailer of the dmg file. Signed-off-by: Peter Wu --- v2: added resource fork offset check --- block/dmg.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/block/dmg.c b/block/dmg.c index 4913249..5f6976b 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -319,7 +319,7 @@ static int dmg_read_resource_fork(BlockDriverState *bs, DmgHeaderState *ds, ret = read_uint32(bs, offset, &count); if (ret < 0) { goto fail; -} else if (count == 0) { +} else if (count == 0 || count > info_end - offset) { ret = -EINVAL; goto fail; } @@ -379,6 +379,11 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, if (ret < 0) { goto fail; } +if (rsrc_fork_offset >= offset || +rsrc_fork_length > offset - rsrc_fork_offset) { +ret = -EINVAL; +goto fail; +} if (rsrc_fork_length != 0) { ret = dmg_read_resource_fork(bs, &ds, rsrc_fork_offset, rsrc_fork_length); Reviewed-by: John Snow
Re: [Qemu-devel] [PATCH v3] configure: Simplify alternate .text segment
Hello, this patch which is part of QEMU for more than a year now needs to be fixed for builds on Mac OS X: I just saw that the Mac's native linker ld does not support --verbose, but shows a warning. Would it be sufficient to redirect that warning to /dev/null (as it was done in the previous code)? Regards Stefan Am 22.06.2013 um 04:10 schrieb Richard Henderson: For bsd-user and linux-user emulation modes QEMU needs to be linked at an alternate .text segment address, so that it's out of the way of the guest executable. Instead of including modified linker scripts for each arch, just set the address with -Ttext-segment if supported, or by using sed to edit the default linker script. Cc: Ed Maste Signed-off-by: Richard Henderson --- configure | 48 +++- 2 files changed, 31 insertions(+), 18 deletions(-) -- Changes v2-v3: * Move the check for textseg_ldflags much earlier in the configure file, so that we've not got cflags invalid for configure time. Plus, the check (and generated ld script) only gets done once, not once per target directory. * Remove ia64 from the hosts that get relocation * Handle s390x like s390. Tested on x86_64, arm, hppa (old binutils needing config-host.ld), sparc64, and ia64. All various versions of linux. r~ diff --git a/configure b/configure index ad32f87..63da418 100755 --- a/configure +++ b/configure @@ -3444,6 +3444,36 @@ if test "$cpu" = "s390x" ; then roms="$roms s390-ccw" fi +# Probe for the need for relocating the user-only binary. +if test "$pie" = "no" ; then + textseg_addr= + case "$cpu" in +arm | hppa | i386 | m68k | ppc | ppc64 | s390* | sparc | sparc64 | x86_64) + textseg_addr=0x6000 + ;; +mips) + textseg_addr=0x40 + ;; + esac + if [ -n "$textseg_addr" ]; then +cat > $TMPC < This $ld --verbose raises a warning when configure is run. +-e '1,/==/d' \ +-e '/==/,$d' \ +-e "s/[.] = [0-9a-fx]* [+] SIZEOF_HEADERS/. = $textseg_addr + SIZEOF_HEADERS/" \ +-e "s/__executable_start = [0-9a-fx]*/__executable_start = $textseg_addr/" > config-host.ld + textseg_ldflags="-Wl,-T../config-host.ld" +fi + fi +fi + # add pixman flags after all config tests are done QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags $fdt_cflags" libs_softmmu="$libs_softmmu $pixman_libs" @@ -4072,9 +4102,6 @@ if test "$gcov" = "yes" ; then echo "GCOV=$gcov_tool" >> $config_host_mak fi -# generate list of library paths for linker script -$ld --verbose -v 2> /dev/null | grep SEARCH_DIR > config-host.ld The old code redirected stderr, so any warning was not visible. - # use included Linux headers if test "$linux" = "yes" ; then mkdir -p linux-headers @@ -4437,21 +4464,8 @@ if test "$gprof" = "yes" ; then fi fi -if test "$ARCH" = "tci"; then - linker_script="" -else - linker_script="-Wl,-T../config-host.ld -Wl,-T,\$(SRC_PATH)/ldscripts/\$(ARCH).ld" -fi - if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then - case "$ARCH" in - alpha | s390x | aarch64) -# The default placement of the application is fine. -;; - *) -ldflags="$linker_script $ldflags" -;; - esac + ldflags="$ldflags $textseg_ldflags" fi echo "LDFLAGS+=$ldflags" >> $config_target_mak
Re: [Qemu-devel] [PATCH 1/2] smbios: Fix dimm size calculation when RAM is multiple of 16GB
On 07/01/2015 18:36, Eduardo Habkost wrote: > The Memory Device size calculation logic is broken when the RAM size is > a multiple of 16GB, making the size of the last entry be 0 instead of > 16GB. Fix the logic to handle that case correctly. > > Signed-off-by: Eduardo Habkost > --- > hw/i386/smbios.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c > index 024e594..ae7032a 100644 > --- a/hw/i386/smbios.c > +++ b/hw/i386/smbios.c > @@ -850,7 +850,8 @@ void smbios_get_tables(uint8_t **tables, size_t > *tables_len, > } > > #define MAX_DIMM_SZ (16ll * ONE_GB) > -#define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ : ram_size % > MAX_DIMM_SZ) > +#define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ \ > +: ((ram_size - 1) % MAX_DIMM_SZ) + 1) > > dimm_cnt = QEMU_ALIGN_UP(ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ; Using "dimm_size = MAX(ram_size, MAX_DIMM_SZ); ram_size -= dimm_size" would have been less weird, but the whole code here is interesting so your patch is just keeping with the style. We all do that. :) Reviewed-by: Paolo Bonzini
Re: [Qemu-devel] [PATCH 2/2] smbios: Don't report unknown CPU speed (fix SVVP regression)
On 07/01/2015 18:36, Eduardo Habkost wrote: > SVVP requires processor speed on Type 4 structures to not be unknown. > This was fixed in SeaBIOS 0.5.0 (in 2009), but the bug was reintroduced > in QEMU 2.1. > > Revert to old behavior and report CPU speed as 2000 MHz instead of > unknown. > > Signed-off-by: Eduardo Habkost > --- > hw/i386/smbios.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c > index ae7032a..12d2137 100644 > --- a/hw/i386/smbios.c > +++ b/hw/i386/smbios.c > @@ -618,8 +618,9 @@ static void smbios_build_type_4_table(unsigned instance) > SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version); > t->voltage = 0; > t->external_clock = cpu_to_le16(0); /* Unknown */ > -t->max_speed = cpu_to_le16(0); /* Unknown */ > -t->current_speed = cpu_to_le16(0); /* Unknown */ > +/* SVVP requires max_speed and current_speed to not be unknown. */ > +t->max_speed = cpu_to_le16(2000); /* 2000 MHz */ > +t->current_speed = cpu_to_le16(2000); /* 2000 MHz */ > t->status = 0x41; /* Socket populated, CPU enabled */ > t->processor_upgrade = 0x01; /* Other */ > t->l1_cache_handle = cpu_to_le16(0x); /* N/A */ > Reviewed-by: Paolo Bonzini
[Qemu-devel] [PATCH 4/4] target-i386: make xmm_regs 512-bit wide
Right now, the AVX512 registers are split in many different fields: xmm_regs for the low 128 bits of the first 16 registers, ymmh_regs for the next 128 bits of the same first 16 registers, zmmh_regs for the next 256 bits of the same first 16 registers, and finally hi16_zmm_regs for the full 512 bits of the second 16 bit registers. This makes it simple to move data in and out of the xsave region, but would be a nightmare for a hypothetical TCG implementation and leads to a proliferation of [XYZ]MM_[BWLSQD] macros. Instead, this patch marshals data manually from the xsave region to a single 32x512-bit array, simplifying the macro jungle and clarifying which bits are in which vmstate subsection. The migration format is unaffected. Signed-off-by: Paolo Bonzini --- target-i386/cpu.h | 68 ++- target-i386/kvm.c | 40 ++ target-i386/machine.c | 55 - 3 files changed, 59 insertions(+), 104 deletions(-) diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 3ecff96..9ad92e2 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -715,31 +715,13 @@ typedef struct SegmentCache { } SegmentCache; typedef union { -uint8_t _b[16]; -uint16_t _w[8]; -uint32_t _l[4]; -uint64_t _q[2]; -float32 _s[4]; -float64 _d[2]; -} XMMReg; - -typedef union { -uint8_t _b[32]; -uint16_t _w[16]; -uint32_t _l[8]; -uint64_t _q[4]; -float32 _s[8]; -float64 _d[4]; -} YMMReg; - -typedef union { uint8_t _b[64]; uint16_t _w[32]; uint32_t _l[16]; uint64_t _q[8]; float32 _s[16]; float64 _d[8]; -} ZMMReg; +} XMMReg; /* really zmm */ typedef union { uint8_t _b[8]; @@ -760,46 +742,18 @@ typedef struct BNDCSReg { } BNDCSReg; #ifdef HOST_WORDS_BIGENDIAN -#define ZMM_B(n) _b[63 - (n)] -#define ZMM_W(n) _w[31 - (n)] -#define ZMM_L(n) _l[15 - (n)] -#define ZMM_S(n) _s[15 - (n)] -#define ZMM_Q(n) _q[7 - (n)] -#define ZMM_D(n) _d[7 - (n)] - -#define YMM_B(n) _b[31 - (n)] -#define YMM_W(n) _w[15 - (n)] -#define YMM_L(n) _l[7 - (n)] -#define YMM_S(n) _s[7 - (n)] -#define YMM_Q(n) _q[3 - (n)] -#define YMM_D(n) _d[3 - (n)] - -#define XMM_B(n) _b[15 - (n)] -#define XMM_W(n) _w[7 - (n)] -#define XMM_L(n) _l[3 - (n)] -#define XMM_S(n) _s[3 - (n)] -#define XMM_Q(n) _q[1 - (n)] -#define XMM_D(n) _d[1 - (n)] +#define XMM_B(n) _b[63 - (n)] +#define XMM_W(n) _w[31 - (n)] +#define XMM_L(n) _l[15 - (n)] +#define XMM_S(n) _s[15 - (n)] +#define XMM_Q(n) _q[7 - (n)] +#define XMM_D(n) _d[7 - (n)] #define MMX_B(n) _b[7 - (n)] #define MMX_W(n) _w[3 - (n)] #define MMX_L(n) _l[1 - (n)] #define MMX_S(n) _s[1 - (n)] #else -#define ZMM_B(n) _b[n] -#define ZMM_W(n) _w[n] -#define ZMM_L(n) _l[n] -#define ZMM_S(n) _s[n] -#define ZMM_Q(n) _q[n] -#define ZMM_D(n) _d[n] - -#define YMM_B(n) _b[n] -#define YMM_W(n) _w[n] -#define YMM_L(n) _l[n] -#define YMM_S(n) _s[n] -#define YMM_Q(n) _q[n] -#define YMM_D(n) _d[n] - #define XMM_B(n) _b[n] #define XMM_W(n) _w[n] #define XMM_L(n) _l[n] @@ -898,17 +852,11 @@ typedef struct CPUX86State { float_status mmx_status; /* for 3DNow! float ops */ float_status sse_status; uint32_t mxcsr; -XMMReg xmm_regs[CPU_NB_REGS]; +XMMReg xmm_regs[CPU_NB_REGS == 8 ? 8 : 32]; XMMReg xmm_t0; MMXReg mmx_t0; -XMMReg ymmh_regs[CPU_NB_REGS]; - uint64_t opmask_regs[NB_OPMASK_REGS]; -YMMReg zmmh_regs[CPU_NB_REGS]; -#ifdef TARGET_X86_64 -ZMMReg hi16_zmm_regs[CPU_NB_REGS]; -#endif /* sysenter registers */ uint32_t sysenter_cs; diff --git a/target-i386/kvm.c b/target-i386/kvm.c index cf9f331..5bfea7e 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1048,7 +1048,7 @@ static int kvm_put_xsave(X86CPU *cpu) CPUX86State *env = &cpu->env; struct kvm_xsave* xsave = env->kvm_xsave_buf; uint16_t cwd, swd, twd; -uint8_t *xmm; +uint8_t *xmm, *ymmh, *zmmh; int i, r; if (!kvm_has_xsave()) { @@ -1071,26 +1071,30 @@ static int kvm_put_xsave(X86CPU *cpu) sizeof env->fpregs); xsave->region[XSAVE_MXCSR] = env->mxcsr; *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV] = env->xstate_bv; -memcpy(&xsave->region[XSAVE_YMMH_SPACE], env->ymmh_regs, -sizeof env->ymmh_regs); memcpy(&xsave->region[XSAVE_BNDREGS], env->bnd_regs, sizeof env->bnd_regs); memcpy(&xsave->region[XSAVE_BNDCSR], &env->bndcs_regs, sizeof(env->bndcs_regs)); memcpy(&xsave->region[XSAVE_OPMASK], env->opmask_regs, sizeof env->opmask_regs); -memcpy(&xsave->region[XSAVE_ZMM_Hi256], env->zmmh_regs, -sizeof env->zmmh_regs); xmm = (uint8_t *)&xsave->region[XSAVE_XMM_SPACE]; -for (i = 0; i < CPU_NB_REGS; i++, xmm += 16) { +ymmh = (uint8_t *)&xsave->region[XSAVE_YMMH_SPACE]; +zmmh = (uint8_t *)&xsave->region[XSAVE_ZMM_Hi256]; +for (i = 0; i < CPU_NB_REGS; i++, xmm += 16, ymmh
[Qemu-devel] [PATCH 3/4] target-i386: use vmstate_offset_sub_array for AVX registers
After the next patch, each vmstate field will extract parts of a larger (32x512-bit) array, so we cannot check the vmstate field against the type of the array. While changing this, change the macros to accept the index of the first element (which will not be 0 for Hi16_ZMM_REGS) instead of the number of elements (which is always CPU_NB_REGS). Signed-off-by: Paolo Bonzini --- include/migration/vmstate.h | 10 ++ target-i386/machine.c | 28 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h index e45fc49..3b9e0de 100644 --- a/include/migration/vmstate.h +++ b/include/migration/vmstate.h @@ -359,6 +359,16 @@ extern const VMStateInfo vmstate_info_bitmap; .offset = vmstate_offset_array(_s, _f, _type*, _n), \ } +#define VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, _num, _version, _vmsd, _type) { \ +.name = (stringify(_field)), \ +.version_id = (_version), \ +.num= (_num), \ +.vmsd = &(_vmsd),\ +.size = sizeof(_type), \ +.flags = VMS_STRUCT|VMS_ARRAY,\ +.offset = vmstate_offset_sub_array(_state, _field, _type, _start), \ +} + #define VMSTATE_STRUCT_ARRAY_TEST(_field, _state, _num, _test, _version, _vmsd, _type) { \ .name = (stringify(_field)), \ .num = (_num), \ diff --git a/target-i386/machine.c b/target-i386/machine.c index 722d62e4..604a49a 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -42,8 +42,9 @@ static const VMStateDescription vmstate_xmm_reg = { } }; -#define VMSTATE_XMM_REGS(_field, _state, _n) \ -VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_xmm_reg, XMMReg) +#define VMSTATE_XMM_REGS(_field, _state, _start) \ +VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, CPU_NB_REGS, 0, \ + vmstate_xmm_reg, XMMReg) /* YMMH format is the same as XMM */ static const VMStateDescription vmstate_ymmh_reg = { @@ -57,8 +58,9 @@ static const VMStateDescription vmstate_ymmh_reg = { } }; -#define VMSTATE_YMMH_REGS_VARS(_field, _state, _n, _v) \ -VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_ymmh_reg, XMMReg) +#define VMSTATE_YMMH_REGS_VARS(_field, _state, _start, _v) \ +VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, CPU_NB_REGS, _v,\ + vmstate_ymmh_reg, XMMReg) static const VMStateDescription vmstate_zmmh_reg = { .name = "zmmh_reg", @@ -73,8 +75,9 @@ static const VMStateDescription vmstate_zmmh_reg = { } }; -#define VMSTATE_ZMMH_REGS_VARS(_field, _state, _n) \ -VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_zmmh_reg, YMMReg) +#define VMSTATE_ZMMH_REGS_VARS(_field, _state, _start) \ +VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, CPU_NB_REGS, 0, \ + vmstate_zmmh_reg, YMMReg) #ifdef TARGET_X86_64 static const VMStateDescription vmstate_hi16_zmm_reg = { @@ -94,8 +97,9 @@ static const VMStateDescription vmstate_hi16_zmm_reg = { } }; -#define VMSTATE_Hi16_ZMM_REGS_VARS(_field, _state, _n) \ -VMSTATE_STRUCT_ARRAY(_field, _state, _n, 0, vmstate_hi16_zmm_reg, ZMMReg) +#define VMSTATE_Hi16_ZMM_REGS_VARS(_field, _state, _start) \ +VMSTATE_STRUCT_SUB_ARRAY(_field, _state, _start, CPU_NB_REGS, 0, \ + vmstate_hi16_zmm_reg, ZMMReg) #endif static const VMStateDescription vmstate_bnd_regs = { @@ -679,9 +683,9 @@ static const VMStateDescription vmstate_avx512 = { .minimum_version_id = 1, .fields = (VMStateField[]) { VMSTATE_UINT64_ARRAY(env.opmask_regs, X86CPU, NB_OPMASK_REGS), -VMSTATE_ZMMH_REGS_VARS(env.zmmh_regs, X86CPU, CPU_NB_REGS), +VMSTATE_ZMMH_REGS_VARS(env.zmmh_regs, X86CPU, 0), #ifdef TARGET_X86_64 -VMSTATE_Hi16_ZMM_REGS_VARS(env.hi16_zmm_regs, X86CPU, CPU_NB_REGS), +VMSTATE_Hi16_ZMM_REGS_VARS(env.hi16_zmm_regs, X86CPU, 0), #endif VMSTATE_END_OF_LIST() } @@ -750,7 +754,7 @@ VMStateDescription vmstate_x86_cpu = { VMSTATE_INT32(env.a20_mask, X86CPU), /* XMM */ VMSTATE_UINT32(env.mxcsr, X86CPU), -VMSTATE_XMM_REGS(env.xmm_regs, X86CPU, CPU_NB_REGS), +VMSTATE_XMM_REGS(env.xmm_regs, X86CPU, 0), #ifdef TARGET_X86_64 VMSTATE_UINT64(env.efer, X86CPU), @@ -803,7 +807,7 @@ VMStateDescription vmstate_x86_cpu = { /* XSAVE related fields */
[Qemu-devel] [PATCH 2/4] target-i386: do not memcpy in and out of xmm_regs
After the next patch, we will move the high parts of AVX and AVX512 registers in the same array as the SSE registers. This will make it impossible to memcpy an array of 128-bit values in and out of xmm_regs in one swoop. Use a for loop instead. Signed-off-by: Paolo Bonzini --- target-i386/kvm.c | 30 -- target-i386/translate.c | 8 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index f92edfe..cf9f331 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -1019,7 +1019,10 @@ static int kvm_put_fpu(X86CPU *cpu) fpu.ftwx |= (!env->fptags[i]) << i; } memcpy(fpu.fpr, env->fpregs, sizeof env->fpregs); -memcpy(fpu.xmm, env->xmm_regs, sizeof env->xmm_regs); +for (i = 0; i < CPU_NB_REGS; i++) { +stq_p(&fpu.xmm[i][0], env->xmm_regs[i].XMM_Q(0)); +stq_p(&fpu.xmm[i][8], env->xmm_regs[i].XMM_Q(1)); +} fpu.mxcsr = env->mxcsr; return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_FPU, &fpu); @@ -1045,6 +1048,7 @@ static int kvm_put_xsave(X86CPU *cpu) CPUX86State *env = &cpu->env; struct kvm_xsave* xsave = env->kvm_xsave_buf; uint16_t cwd, swd, twd; +uint8_t *xmm; int i, r; if (!kvm_has_xsave()) { @@ -1065,8 +1069,6 @@ static int kvm_put_xsave(X86CPU *cpu) memcpy(&xsave->region[XSAVE_CWD_RDP], &env->fpdp, sizeof(env->fpdp)); memcpy(&xsave->region[XSAVE_ST_SPACE], env->fpregs, sizeof env->fpregs); -memcpy(&xsave->region[XSAVE_XMM_SPACE], env->xmm_regs, -sizeof env->xmm_regs); xsave->region[XSAVE_MXCSR] = env->mxcsr; *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV] = env->xstate_bv; memcpy(&xsave->region[XSAVE_YMMH_SPACE], env->ymmh_regs, @@ -1079,6 +1081,13 @@ static int kvm_put_xsave(X86CPU *cpu) sizeof env->opmask_regs); memcpy(&xsave->region[XSAVE_ZMM_Hi256], env->zmmh_regs, sizeof env->zmmh_regs); + +xmm = (uint8_t *)&xsave->region[XSAVE_XMM_SPACE]; +for (i = 0; i < CPU_NB_REGS; i++, xmm += 16) { +stq_p(xmm, env->xmm_regs[i].XMM_Q(0)); +stq_p(xmm+8, env->xmm_regs[i].XMM_Q(1)); +} + #ifdef TARGET_X86_64 memcpy(&xsave->region[XSAVE_Hi16_ZMM], env->hi16_zmm_regs, sizeof env->hi16_zmm_regs); @@ -1384,7 +1393,10 @@ static int kvm_get_fpu(X86CPU *cpu) env->fptags[i] = !((fpu.ftwx >> i) & 1); } memcpy(env->fpregs, fpu.fpr, sizeof env->fpregs); -memcpy(env->xmm_regs, fpu.xmm, sizeof env->xmm_regs); +for (i = 0; i < CPU_NB_REGS; i++) { +env->xmm_regs[i].XMM_Q(0) = ldq_p(&fpu.xmm[i][0]); +env->xmm_regs[i].XMM_Q(1) = ldq_p(&fpu.xmm[i][8]); +} env->mxcsr = fpu.mxcsr; return 0; @@ -1395,6 +1407,7 @@ static int kvm_get_xsave(X86CPU *cpu) CPUX86State *env = &cpu->env; struct kvm_xsave* xsave = env->kvm_xsave_buf; int ret, i; +const uint8_t *xmm; uint16_t cwd, swd, twd; if (!kvm_has_xsave()) { @@ -1421,8 +1434,6 @@ static int kvm_get_xsave(X86CPU *cpu) env->mxcsr = xsave->region[XSAVE_MXCSR]; memcpy(env->fpregs, &xsave->region[XSAVE_ST_SPACE], sizeof env->fpregs); -memcpy(env->xmm_regs, &xsave->region[XSAVE_XMM_SPACE], -sizeof env->xmm_regs); env->xstate_bv = *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV]; memcpy(env->ymmh_regs, &xsave->region[XSAVE_YMMH_SPACE], sizeof env->ymmh_regs); @@ -1434,6 +1445,13 @@ static int kvm_get_xsave(X86CPU *cpu) sizeof env->opmask_regs); memcpy(env->zmmh_regs, &xsave->region[XSAVE_ZMM_Hi256], sizeof env->zmmh_regs); + +xmm = (const uint8_t *)&xsave->region[XSAVE_XMM_SPACE]; +for (i = 0; i < CPU_NB_REGS; i++, xmm += 16) { +env->xmm_regs[i].XMM_Q(0) = ldq_p(xmm); +env->xmm_regs[i].XMM_Q(1) = ldq_p(xmm+8); +} + #ifdef TARGET_X86_64 memcpy(env->hi16_zmm_regs, &xsave->region[XSAVE_Hi16_ZMM], sizeof env->hi16_zmm_regs); diff --git a/target-i386/translate.c b/target-i386/translate.c index 5af4300..253009a 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -2621,10 +2621,10 @@ static inline void gen_sto_env_A0(DisasContext *s, int offset) static inline void gen_op_movo(int d_offset, int s_offset) { -tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset); -tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset); -tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + 8); -tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + 8); +tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(XMMReg, XMM_Q(0)); +tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(XMMReg, XMM_Q(0)); +tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(XMMReg, XMM_Q(1)); +tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(XMMReg, XMM_Q(1)); } static inline void gen_op_movq(int d_offset, int s_offset) -- 1.8.3.1
[Qemu-devel] [PATCH 0/3] target-i386: rework how AVX/AVX512 registers are stored
Right now, AVX and AVX512 registers are stored part in the SSE registers, part in separate fields that follow the XSAVE format. This series instead uses a single 512-bit field for each of the 32 registers. It makes the marshalling a bit more complicated but keeps the madness out of CPUX86State's public interface. Also, a hypothetical XSAVE implementation of TCG would probably need something like this too, and it could share most of the implementation with KVM's kvm_get_xsave/kvm_put_xsave wrappers. As a bonus, patch 1 fixes a real bug found while inspecting uses of xmm_regs. Paolo Paolo Bonzini (4): target-i386: fix movntsd on big-endian hosts target-i386: do not memcpy in and out of xmm_regs target-i386: use vmstate_offset_sub_array for AVX registers target-i386: make xmm_regs 512-bit wide include/migration/vmstate.h | 10 +++ target-i386/cpu.h | 68 + target-i386/kvm.c | 62 +++--- target-i386/machine.c | 73 +++-- target-i386/translate.c | 11 +++ 5 files changed, 106 insertions(+), 118 deletions(-) -- 1.8.3.1
[Qemu-devel] [PATCH 1/4] target-i386: fix movntsd on big-endian hosts
This was accessing an XMM register's low half without going through XMM_Q. Cc: qemu-sta...@nongnu.org Signed-off-by: Paolo Bonzini --- target-i386/translate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target-i386/translate.c b/target-i386/translate.c index ebdc350..5af4300 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -3074,7 +3074,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, goto illegal_op; gen_lea_modrm(env, s, modrm); if (b1 & 1) { -gen_stq_env_A0(s, offsetof(CPUX86State, xmm_regs[reg])); +gen_stq_env_A0(s, offsetof(CPUX86State, + xmm_regs[reg].XMM_Q(0))); } else { tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State, xmm_regs[reg].XMM_L(0))); -- 1.8.3.1
Re: [Qemu-devel] Gives user ability to select endian format for video display - fixes Mac OS X guest color issue.
On Jan 7, 2015, at 5:35 AM, Paolo Bonzini wrote: > > > On 06/01/2015 22:33, G 3 wrote: >> >> 00:01.0 VGA compatible controller: Technical Corp. Device (rev >> 02) (prog-if 00 [VGA controller]) >>Subsystem: Qumranet, Inc. Device 1100 >>Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- >> ParErr- Stepping- SERR- FastB2B- DisINTx- >>Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- >> SERR- >Region 0: Memory at 8000 (32-bit, prefetchable) [size=16M] >>Region 2: Memory at 8100 (32-bit, non-prefetchable) [size=4K] >>Expansion ROM at 8101 [disabled] [size=64K] > > Yes. So this is "-vga std", not "-vga cirrus". In this case, it might > make sense to add a property to the VGA that forces an endianness over > the other, and then to specify that property in order to use Mac OS X. > > However, you should specify it whatever the host endianness and the host > OS is. If this is not the case, you're just exchanging a bug with another. > > If something > > a) works with Linux host but not with Mac OS X host > > b) and works with Linux guest but not with Mac OS X guest > > the only logical explanation is that you have more than one bug, and > they somehow cancel each other. The fix is to find and stomp all the > bugs, not to introduce an option for the cases that end up buggy. I was told there is a frame buffer byte swap in Linux, that is why the colors appear correctly. But if that happened all the time, then Linux guest would have the color problem. Maybe we should all makes theories and guest where to look. Here is my theories so far: - Incorrect OpenBIOS settings - VGA isn't correctly supported in Mac OS X - Vague standards that didn't take endianness of processor into account - Some function of VGA not implemented or not implemented fully - Some assumption about writing to IO ports that is true on real Macs but not implemented on QEMU If anyone wants to add to the list, please do so. -Incorrect OpenBIOS settings If this is true, it wouldn't be the first time OpenBIOS issues have effected Mac OS X. - VGA isn't correctly supported in Mac OS X: If there is someone out there that has some early VGA PCI card, and a PowerMac that runs Mac OS X, it would help a lot to let us know if it displays colors correctly. I am pretty sure all such cards were made for PC's only, so this would probably not work. I'm surprised Apple implemented a generic VGA driver in the first place. - Vague standards that didn't take endianness of processor into account Never seen any mention of endianness of pixel data in the VGA standards. It was probably just assumed little endian. - Some function of VGA not implemented or not implemented fully This could be a possibility, but not sure about it. - Some assumption about writing to IO ports that is true on real Macs but not implemented on QEMU This is just a guess for now. It would take a lot of memory poking to prove this.
[Qemu-devel] [PATCH 1/2] smbios: Fix dimm size calculation when RAM is multiple of 16GB
The Memory Device size calculation logic is broken when the RAM size is a multiple of 16GB, making the size of the last entry be 0 instead of 16GB. Fix the logic to handle that case correctly. Signed-off-by: Eduardo Habkost --- hw/i386/smbios.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c index 024e594..ae7032a 100644 --- a/hw/i386/smbios.c +++ b/hw/i386/smbios.c @@ -850,7 +850,8 @@ void smbios_get_tables(uint8_t **tables, size_t *tables_len, } #define MAX_DIMM_SZ (16ll * ONE_GB) -#define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ : ram_size % MAX_DIMM_SZ) +#define GET_DIMM_SZ ((i < dimm_cnt - 1) ? MAX_DIMM_SZ \ +: ((ram_size - 1) % MAX_DIMM_SZ) + 1) dimm_cnt = QEMU_ALIGN_UP(ram_size, MAX_DIMM_SZ) / MAX_DIMM_SZ; -- 1.9.3
[Qemu-devel] [PATCH 2/2] smbios: Don't report unknown CPU speed (fix SVVP regression)
SVVP requires processor speed on Type 4 structures to not be unknown. This was fixed in SeaBIOS 0.5.0 (in 2009), but the bug was reintroduced in QEMU 2.1. Revert to old behavior and report CPU speed as 2000 MHz instead of unknown. Signed-off-by: Eduardo Habkost --- hw/i386/smbios.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/i386/smbios.c b/hw/i386/smbios.c index ae7032a..12d2137 100644 --- a/hw/i386/smbios.c +++ b/hw/i386/smbios.c @@ -618,8 +618,9 @@ static void smbios_build_type_4_table(unsigned instance) SMBIOS_TABLE_SET_STR(4, processor_version_str, type4.version); t->voltage = 0; t->external_clock = cpu_to_le16(0); /* Unknown */ -t->max_speed = cpu_to_le16(0); /* Unknown */ -t->current_speed = cpu_to_le16(0); /* Unknown */ +/* SVVP requires max_speed and current_speed to not be unknown. */ +t->max_speed = cpu_to_le16(2000); /* 2000 MHz */ +t->current_speed = cpu_to_le16(2000); /* 2000 MHz */ t->status = 0x41; /* Socket populated, CPU enabled */ t->processor_upgrade = 0x01; /* Other */ t->l1_cache_handle = cpu_to_le16(0x); /* N/A */ -- 1.9.3
[Qemu-devel] [PATCH 0/2] smbios: Fixes for SVVP tests
Some changed introduced by the new QEMU smbios table generation code broke SVVP. This series fixes those issues. Eduardo Habkost (2): smbios: Fix dimm size calculation when RAM is multiple of 16GB smbios: Don't report unknown CPU speed (fix SVVP regression) hw/i386/smbios.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) -- 1.9.3
[Qemu-devel] [PATCH v2] vfio-pci: Fix BAR size overflow
We use an unsigned int when working with the PCI BAR size, which can obviously overflow if the BAR is 4GB or larger. This needs to change to a fixed length uint64_t. A similar issue is possible, though even more unlikely, when mapping the region above an MSI-X table. The start of the MSI-X vector table must be below 4GB, but the end, and therefore the start of the next mapping region, could still land at 4GB. Suggested-by: Nishank Trivedi Signed-off-by: Alex Williamson --- v2: s/unsigned long/uint64_t/, duh hw/vfio/pci.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index b4e73d1..b6703c7 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -2301,7 +2301,7 @@ static void vfio_unmap_bar(VFIOPCIDevice *vdev, int nr) static void vfio_map_bar(VFIOPCIDevice *vdev, int nr) { VFIOBAR *bar = &vdev->bars[nr]; -unsigned size = bar->region.size; +uint64_t size = bar->region.size; char name[64]; uint32_t pci_bar; uint8_t type; @@ -2351,7 +2351,7 @@ static void vfio_map_bar(VFIOPCIDevice *vdev, int nr) } if (vdev->msix && vdev->msix->table_bar == nr) { -unsigned start; +uint64_t start; start = HOST_PAGE_ALIGN(vdev->msix->table_offset + (vdev->msix->entries * PCI_MSIX_ENTRY_SIZE));
Re: [Qemu-devel] [PATCH v8 3/3] hw/arm/virt: add dynamic sysbus device support
Hi Peter, On 01/06/2015 07:57 PM, Peter Maydell wrote: > On 5 January 2015 at 16:14, Eric Auger wrote: >> Allows sysbus devices to be instantiated from command line by >> using -device option. Machvirt creates a platform bus at init. >> The dynamic sysbus devices are attached to this platform bus device. > >> @@ -59,6 +61,8 @@ >> #define GIC_FDT_IRQ_PPI_CPU_START 8 >> #define GIC_FDT_IRQ_PPI_CPU_WIDTH 8 >> >> +#define PLATFORM_BUS_NUM_IRQS 20 >> + >> enum { >> VIRT_FLASH, >> VIRT_MEM, >> @@ -69,8 +73,11 @@ enum { >> VIRT_MMIO, >> VIRT_RTC, >> VIRT_FW_CFG, >> +VIRT_PLATFORM_BUS, >> }; >> >> +static ARMPlatformBusSystemParams platform_bus_params; >> + >> typedef struct MemMapEntry { >> hwaddr base; >> hwaddr size; >> @@ -119,24 +126,26 @@ typedef struct { >> */ >> static const MemMapEntry a15memmap[] = { >> /* Space up to 0x800 is reserved for a boot ROM */ >> -[VIRT_FLASH] = { 0, 0x0800 }, >> -[VIRT_CPUPERIPHS] = { 0x0800, 0x0002 }, >> +[VIRT_FLASH] = { 0, 0x0800 }, >> +[VIRT_CPUPERIPHS] = { 0x0800, 0x0002 }, >> /* GIC distributor and CPU interfaces sit inside the CPU peripheral >> space */ >> -[VIRT_GIC_DIST] = { 0x0800, 0x0001 }, >> -[VIRT_GIC_CPU] ={ 0x0801, 0x0001 }, >> -[VIRT_UART] = { 0x0900, 0x1000 }, >> -[VIRT_RTC] ={ 0x0901, 0x1000 }, >> -[VIRT_FW_CFG] = { 0x0902, 0x000a }, >> -[VIRT_MMIO] = { 0x0a00, 0x0200 }, >> +[VIRT_GIC_DIST] = { 0x0800, 0x0001 }, >> +[VIRT_GIC_CPU] ={ 0x0801, 0x0001 }, >> +[VIRT_UART] = { 0x0900, 0x1000 }, >> +[VIRT_RTC] ={ 0x0901, 0x1000 }, >> +[VIRT_FW_CFG] = { 0x0902, 0x000a }, > > Please don't re-indent unrelated lines in the same patch: it makes > it very hard to tell whether any of them have actually changed. sure I will create another patch file dedicated to that > >> +[VIRT_PLATFORM_BUS] = { 0x0940, 0x0040 }, >> +[VIRT_MMIO] = { 0x0a00, 0x0200 }, >> /* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size >> */ >> /* 0x1000 .. 0x4000 reserved for PCI */ >> -[VIRT_MEM] ={ 0x4000, 30ULL * 1024 * 1024 * 1024 }, >> +[VIRT_MEM] ={ 0x4000, 30ULL * 1024 * 1024 * 1024 }, >> }; >> >> static const int a15irqmap[] = { >> [VIRT_UART] = 1, >> [VIRT_RTC] = 2, >> [VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */ >> +[VIRT_PLATFORM_BUS] = 48, /* .. to 48 + PLATFORM_BUS_NUM_IRQS -1*/ > > Missing spaces again (also use '...to' for consistency with line above). > >> }; > > This patch generally looks OK, so I think the major question is: > are we happy with this memory and IRQ usage? > > Why 20 for PLATFORM_BUS_NUM_IRQS? It seems a funny number. > Starting the platform bus IRQs at 48 means there is no scope > at all for raising NUM_VIRTIO_TRANSPORTS later, which is > not really what I had in mind, though in fact it seems > unlikely that we'll ever really want to do that given the > imminent advent of PCI. Still, I don't think it would > hurt to start at 64. Then I will start at 64. About PLATFORM_BUS_NUM_IRQS= 20, I must acknowledge it is an arbitrary figure. Alex used 10 in e500 as default value. If I am not wrong a DMA330 can have up to 32 IRQ. It is another candidate for VFIO. Would it be OK to use 32 instead of 20? About memory, here we have space for 64 64kB pages. any other suggestions? > we have >> static VirtBoardInfo machines[] = { >> @@ -556,6 +565,47 @@ static void create_fw_cfg(const VirtBoardInfo *vbi) >> g_free(nodename); >> } >> >> +static void create_platform_bus(VirtBoardInfo *vbi, qemu_irq *pic) >> +{ >> +DeviceState *dev; >> +SysBusDevice *s; >> +int i; >> +ARMPlatformBusFdtParams *fdt_params = g_new(ARMPlatformBusFdtParams, 1); > > ...does the arm_register_platform_bus_fdt_creator() function > implicitly agree to g_free() the pointer it's passed when it's > done with it, or are we just leaking this? Well I could deallocate in platform_bus_fdt_notify routine if you recommend to do so. Thanks for the review. Eric > > thanks > -- PMM >
Re: [Qemu-devel] [PATCH 0/6] relicense QEMU softfloat from 2b to to 2a
On 07/01/2015 17:34, Peter Maydell wrote: >>> >> # All Red Hat contributions (at least Avi, Juan, me; don't know about >>> >> rth) >>> >> # are available under GPLv2+; also other authors agreed on it. For this >>> >> # particular license, >>> >> # Acked-by: Paolo Bonzini >>> >> >>> >> and Juan said: >>> >> # As said by paolo, any contribution by me is under GPLv2+ O:-) >>> >> >>> >> which I took to mean that the RH contribs were GPLv2+, not SF2a. >> > >> > I was not counting rth, because I don't know what he did on company time >> > and what he did on his own, and he's not on the virt team too. > Right, but I assumed when you said "this particular license" you > meant GPLv2+, not SF2a... Ah... For extra clarity what I meant was "strictly speaking RH contributors except possibly rth already have relicensed all their QEMU contributions under a license that is compatible with the rest of QEMU; but I am also okay with SF2a. Paolo
Re: [Qemu-devel] [PATCH 0/4] ARM: Add support for a generic PCI Express host bridge
On 7 January 2015 at 14:26, Claudio Fontana wrote: > Yes I did but it seems it's not picking up the CONFIG_PCI_GENERIC=y for some > reason. > If I force hw/pci-host/Makefile.objs to build it by making it a common-obj-y > then it builds. This is a long-standing bug in our makefiles: http://lists.gnu.org/archive/html/qemu-devel/2014-06/msg04850.html where there is a dependency on default-configs/$TARGET.mak but not on any .mak files which are included by that file. -- PMM
Re: [Qemu-devel] [PATCH 0/6] relicense QEMU softfloat from 2b to to 2a
On 7 January 2015 at 16:29, Paolo Bonzini wrote: > On 07/01/2015 17:23, Peter Maydell wrote: >> On 7 January 2015 at 11:04, Paolo Bonzini wrote: >> You said >> # All Red Hat contributions (at least Avi, Juan, me; don't know about rth) >> # are available under GPLv2+; also other authors agreed on it. For this >> # particular license, >> # Acked-by: Paolo Bonzini >> >> and Juan said: >> # As said by paolo, any contribution by me is under GPLv2+ O:-) >> >> which I took to mean that the RH contribs were GPLv2+, not SF2a. > > I was not counting rth, because I don't know what he did on company time > and what he did on his own, and he's not on the virt team too. Right, but I assumed when you said "this particular license" you meant GPLv2+, not SF2a... -- PMM
[Qemu-devel] [Bug 1391942] Re: Unnecessary events option of the trace argument with UST backend
It works without the -trace option. Want I meant with this post is that the "events" argument of the "-trace" option has no effect in the case of using LTTng UST as the tracing backend because the events are enabled from the LTTng tracer itself. Is there some way I can make an argument optional or conditional to a tracing framework? Thanks, Francis -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1391942 Title: Unnecessary events option of the trace argument with UST backend Status in QEMU: New Bug description: When running configure with the --enable-trace-backends=ust option and compiling. The user should not have to specify a the "events" and "file" options because they are not used with that tracing framework. Right now, in order the use this option the need to specify a dummy events file. This fails: $> qemu-system-x86_64 -hda debian_wheezy_amd64_standard.qcow2 -trace -m 512 qemu-system-x86_64: -trace -m: Invalid parameter '-m' This works: $> qemu-system-x86_64 -hda debian_wheezy_amd64_standard.qcow2 -trace events=dummy-events.txt -m 512 VNC server running on `127.0.0.1:5900' I am using version: $> qemu-system-x86_64 --version QEMU emulator version 2.1.90, Copyright (c) 2003-2008 Fabrice Bellard To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1391942/+subscriptions
Re: [Qemu-devel] [PATCH 0/6] relicense QEMU softfloat from 2b to to 2a
On 07/01/2015 17:23, Peter Maydell wrote: > On 7 January 2015 at 11:04, Paolo Bonzini wrote: >> >> >> On 07/01/2015 11:34, Peter Maydell wrote: >>> The thing is that after all these relicensings we end up with a >>> file with a mix of licenses in it. So for somebody actually >>> using the file the controlling license is GPLv2+. (In particular >>> all the RedHat contributions are GPLv2+, not SoftFloat-2a...) >> >> Actually, all four of us (I and Avi and Juan and Luiz) acked the change, >> so Red Hat contributions are SoftFloat-2a. > > You said > # All Red Hat contributions (at least Avi, Juan, me; don't know about rth) > # are available under GPLv2+; also other authors agreed on it. For this > # particular license, > # Acked-by: Paolo Bonzini > > and Juan said: > # As said by paolo, any contribution by me is under GPLv2+ O:-) > > which I took to mean that the RH contribs were GPLv2+, not SF2a. I was not counting rth, because I don't know what he did on company time and what he did on his own, and he's not on the virt team too. rth and Avi agreed on SoftFloat-2a license separately. Juan was the only one to reply to my message above, and his reply http://lists.gnu.org/archive/html/qemu-devel/2013-04/msg05849.html is somewhat contradictory; he mentions GPLv2 but his explicit Acked-by was below my own Acked-by "for this particular license". I took that as a SoftFloat-2a ack too when I reviewed the commits and threads this morning. But... > Anyway, we can make the future-changes license sf2a regardless > of what license the RH contribs in the past are under (we have > the non-SF2a BSD contribs as well so the license of the whole > file is never going to be a single simple thing). ... this is true anyway. Paolo
Re: [Qemu-devel] [PATCH RFC v6 19/20] virtio-blk: revision specific feature bits
On Sun, 28 Dec 2014 12:24:46 +0200 "Michael S. Tsirkin" wrote: > On Thu, Dec 11, 2014 at 02:25:21PM +0100, Cornelia Huck wrote: > > Wire up virtio-blk to provide different feature bit sets depending > > on whether legacy or v1.0 has been requested. > > > > Note that VERSION_1 is still disabled due to missing ANY_LAYOUT support. > > > > Signed-off-by: Cornelia Huck > > So we need some way for devices to tell transports > not to negotiate rev 1. > Does clearing VERSION_1 have this effect? > I just noticed that my patch is running in circles here. What we need is probably the transport-dependent maximum revision checker (which at least for ccw is acting on a device) pass in the requested revision and check if the feature bits for the revision include VERSION_1. Does that make sense?
Re: [Qemu-devel] Gives user ability to select endian format for video display - fixes Mac OS X guest color issue.
On Jan 7, 2015, at 9:43 AM, Gerd Hoffmann wrote: > Hi, > >> However, you should specify it whatever the host endianness and the host >> OS is. If this is not the case, you're just exchanging a bug with another. >> >> If something >> >> a) works with Linux host but not with Mac OS X host >> >> b) and works with Linux guest but not with Mac OS X guest >> >> the only logical explanation is that you have more than one bug, and >> they somehow cancel each other. > > It isn't that simple I think. Linux and MacOS X using different video > modes could also have this effect. Also there are a number of ways > linux can drive the video card, depending on the kernel version. > kernels 3.14+ have a drm driver for the qemu stdvga, which runs the card > with 32bpp (if enabled). On older kernels the only option is offb, > which IIRC by default runs with 8bpp modes. Also offb has quirks to set > the palette registers on the qemu stdvga. > > So, one interesting question is how MacOS X drives the video card? Just > using what openfirmware has initialized? Which video mode? That is an intriguing idea. What if the problem is with openbios? I wonder if it is as simple as settings a property in a node. > > Turning on DEBUG_VGA in vga.c should help shed a light on what the guest > is doing and which video mode is active. I turned on all debug options in vga.c. Here is the output: VGA: write addr=0x03c0 data=0x00 VBE: write index=0x4 val=0x0 VBE: write index=0x8 val=0x0 VBE: write index=0x9 val=0x0 VBE: write index=0x1 val=0x320 VBE: write index=0x2 val=0x258 VBE: write index=0x3 val=0x20 VBE: write index=0x4 val=0x1 VGA: write addr=0x03c0 data=0x00 VGA: write addr=0x03c0 data=0x20 VGA: Using shared surface for depth=32 swap=1 VGA: write addr=0x03c8 data=0x00 VGA: write addr=0x03c9 data=0x00 VGA: write addr=0x03c9 data=0x00 VGA: write addr=0x03c9 data=0x00 VGA: write addr=0x03c8 data=0x01 VGA: write addr=0x03c9 data=0x00 VGA: write addr=0x03c9 data=0x00 VGA: write addr=0x03c9 data=0x00 VGA: write addr=0x03c8 data=0x02 VGA: write addr=0x03c9 data=0x00 VGA: write addr=0x03c9 data=0x00 VGA: write addr=0x03c9 data=0x00 VGA: write addr=0x03c8 data=0x03 VGA: write addr=0x03c9 data=0x00 VGA: write addr=0x03c9 data=0x00 VGA: write addr=0x03c9 data=0x00 VGA: write addr=0x03c8 data=0x04 VGA: write addr=0x03c9 data=0x01 VGA: write addr=0x03c9 data=0x01 VGA: write addr=0x03c9 data=0x01 VGA: write addr=0x03c8 data=0x05 VGA: write addr=0x03c9 data=0x01 VGA: write addr=0x03c9 data=0x01 VGA: write addr=0x03c9 data=0x01 VGA: write addr=0x03c8 data=0x06 > > Also: what UI is in use? cocoa? gtk? sdl? Has using another ui > (assuming it is available on macosx hosts) any effect? Cocoa is what I am using. There are currently no other UI's available on Mac OS X.
Re: [Qemu-devel] [PATCH 0/2] ATAPI migration fix/hack
Oops, forgot to include Kevin and Stefan on cc for this. Dave * Dr. David Alan Gilbert (git) (dgilb...@redhat.com) wrote: > From: "Dr. David Alan Gilbert" > > This pair of patches fixes a problem where IDE/ATAPI cdrom > reads get lost/corrupted over migration. > > The first of the patches (restore atapi_dma flag) is > a simple fix that I think is safe; it no longer causes > corruption in the case we saw, but does still trigger > a long timeout. > > The second is a hack; it throws a medium error causing > the guest to retry the command in the case where migration > happens just between the IDE/ATAPI command being submitted > and the bmdma being finished. This recovers a lot > faster than the timeout. > > Only tried on Linux guests so far; I think it might be possible > to replace both of these by reparsing the command buffer for > ATAPI; I'm just not confident I know when that's safe to do, > and I wanted to see how disgusted people were by the 2nd hack. > > Dave > > Dr. David Alan Gilbert (2): > Restore atapi_dma flag across migration > atapi migration: Throw recoverable error to avoid recovery > > hw/ide/atapi.c| 17 + > hw/ide/core.c | 1 + > hw/ide/internal.h | 2 ++ > hw/ide/pci.c | 11 +++ > 4 files changed, 31 insertions(+) > > -- > 2.1.0 > > -- Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK
Re: [Qemu-devel] [PATCH 0/6] relicense QEMU softfloat from 2b to to 2a
On 7 January 2015 at 11:04, Paolo Bonzini wrote: > > > On 07/01/2015 11:34, Peter Maydell wrote: >> The thing is that after all these relicensings we end up with a >> file with a mix of licenses in it. So for somebody actually >> using the file the controlling license is GPLv2+. (In particular >> all the RedHat contributions are GPLv2+, not SoftFloat-2a...) > > Actually, all four of us (I and Avi and Juan and Luiz) acked the change, > so Red Hat contributions are SoftFloat-2a. You said # All Red Hat contributions (at least Avi, Juan, me; don't know about rth) # are available under GPLv2+; also other authors agreed on it. For this # particular license, # Acked-by: Paolo Bonzini and Juan said: # As said by paolo, any contribution by me is under GPLv2+ O:-) which I took to mean that the RH contribs were GPLv2+, not SF2a. >> So it seemed simplest to say 'GPLv2+ for future changes'; but >> it wouldn't make any major difference to pick softfloat-2a I guess >> (and that is the license covering the bulk of the code so it >> does make more sense in some ways). > > Yes, that was my reasoning. Anyway, we can make the future-changes license sf2a regardless of what license the RH contribs in the past are under (we have the non-SF2a BSD contribs as well so the license of the whole file is never going to be a single simple thing). -- PMM
Re: [Qemu-devel] [PATCH RFC v6 18/20] virtio: support revision-specific features
On Sun, 28 Dec 2014 10:32:06 +0200 "Michael S. Tsirkin" wrote: > On Thu, Dec 11, 2014 at 02:25:20PM +0100, Cornelia Huck wrote: > > Devices may support different sets of feature bits depending on which > > revision they're operating at. Let's give the transport a way to > > re-query the device about its features when the revision has been > > changed. > > > > Signed-off-by: Cornelia Huck > > So now we have both get_features and get_features_rev, and > it's never clear which revision does host_features refer to. > IMHO that's just too messy. > Let's add get_legacy_features and host_legacy_features instead? I wanted to avoid touching anything that does not support version 1. And this interface might still work for later revisions, no?
Re: [Qemu-devel] [PATCH] include/qom/cpu.h: Add missing documentation for some CPUClass methods
Hi, Am 05.01.2015 um 20:54 schrieb Greg Kurz: > On Mon, 5 Jan 2015 14:23:32 + > Peter Maydell wrote: > >> The CPUClass QOM methods virtio_is_big_endian, write_elf{32,64}_note >> and write_elf{32,64}_qemunote were added without any description >> being added to the doc comment. Correct this omission. >> >> Signed-off-by: Peter Maydell >> --- > > Thanks for this accurate description of virtio_is_big_endian. > > Acked-by: Greg Kurz > >> More informative phrasings for the elf note callbacks welcome... >> >> include/qom/cpu.h | 12 >> 1 file changed, 12 insertions(+) >> >> diff --git a/include/qom/cpu.h b/include/qom/cpu.h >> index 2098f1c..f2d7de1 100644 >> --- a/include/qom/cpu.h >> +++ b/include/qom/cpu.h >> @@ -82,6 +82,10 @@ struct TranslationBlock; >> * @do_unassigned_access: Callback for unassigned access handling. >> * @do_unaligned_access: Callback for unaligned access handling, if >> * the target defines #ALIGNED_ONLY. >> + * @virtio_is_big_endian: Callback to return true if a CPU which supports %true >> + * runtime configurable endianness is currently big-endian. Non-configurable >> + * CPUs can use the default implementation of this method. This method >> should >> + * not be used by any callers other than the pre-1.0 virtio devices. >> * @memory_rw_debug: Callback for GDB memory access. >> * @dump_state: Callback for dumping state. >> * @dump_statistics: Callback for dumping statistics. >> @@ -96,6 +100,14 @@ struct TranslationBlock; >> * @gdb_read_register: Callback for letting GDB read a register. >> * @gdb_write_register: Callback for letting GDB write a register. >> * @debug_excp_handler: Callback for handling debug exceptions. >> + * @write_elf64_note: Callback for writing a CPU-specific ELF note to a >> + * 64-bit VM coredump. >> + * @write_elf32_qemunote: Callback for writing a CPU- and QEMU-specific ELF >> + * note to a 32 bit VM coredump. >> + * @write_elf32_note: Callback for writing a CPU-specific ELF note to a >> + * 32-bit VM coredump. >> + * @write_elf32_qemunote: Callback for writing a CPU- and QEMU-specific ELF >> + * note to a 32 bit VM coredump. Let's consistently use "32-bit". :) >> * @vmsd: State description for migration. >> * @gdb_num_core_regs: Number of core registers accessible to GDB. >> * @gdb_core_xml_file: File name for core registers GDB XML description. Thanks, applied to qom-cpu with those changes: https://github.com/afaerber/qemu-cpu/commits/qom-cpu Regards, Andreas -- SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany GF: Felix Imendörffer, Jane Smithard, Jennifer Guild, Dilip Upmanyu, Graham Norton; HRB 21284 (AG Nürnberg)
[Qemu-devel] [Bug 1404278] Re: tap connections not working on windows host
I have tried what you suggested (breaking the bridge on the host, and giving the host tap 192.168.5.1 and the guest eth0 192.168.5.2 and tried pinging one from the other. I get 100% packet loss. This points to QEMU's tap networking as far as I can see. I have tried uninstalling the 64 bit version and installing the 32bit tap adapter (and bridging it) from openvpn 2.3.6-I601 but that didn't seem to make any difference. I tried using a very old qemu (0.11.1) with qemu manager and the 32bit tap adapter and bridge set up (using the same disk image but specifying intel E1000 netcard for the vm) and that works. so some time between 0.11.1 and 2.0 tap networking has got broken. I can spend some more time trying stuff out if you have any suggestions. There must be some people actually using the windows host qemu and tap somewhere! :-) (I don't have any problems running with a linux host and tap bridged network - well a few errors, but it (networking) seems to work anyway) -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1404278 Title: tap connections not working on windows host Status in QEMU: New Bug description: using latest qemu 2.2.0 64bit for windows host (installed from qemu-w64-setup-20141210.exe obtained from http://qemu.weilnetz.de/w64/ ),OpenVPN 2.6.3-I601 64bit tap adapter named tap01 and calling qemu using the following. qemu-system-x86_64.exe -m 512 -net nic -net tap,ifname=tap01 -hda "c:\\data\\images\\test.img" where the image contains a slackware 14.0 64bit install. The tap is bridged with the real network adapter and the bridge is given an ip of 10.1.1.41 (which works as the ip for the windows host). The tap adapter (in network connections) shows connected when the qemu vm is running. inside the vm, the network is given an ip of 10.1.1.143 (the netmask and default gateway are the same for the virtual and real pc). fault. The vm cannot see the rest of the local network or visa-versa. This used to work in early (0.9 32bit) versions of qemu. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1404278/+subscriptions