mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 02:03:56 -06:00
Merge branch 'qom-cpu' of git://repo.or.cz/qemu/afaerber
* 'qom-cpu' of git://repo.or.cz/qemu/afaerber: MAINTAINERS: Include X86CPU in CPU maintenance area cpu: Move kvm_run into CPUState cpu: Move kvm_state field into CPUState ppc_booke: Pass PowerPCCPU to ppc_booke_timers_init() ppc4xx_devs: Return PowerPCCPU from ppc4xx_init() ppc_booke: Pass PowerPCCPU to {decr,fit,wdt} timer callbacks ppc: Pass PowerPCCPU to [h]decr timer callbacks ppc: Pass PowerPCCPU to [h]decr callbacks ppc: Pass PowerPCCPU to ppc_set_irq() kvm: Pass CPUState to kvm_vcpu_ioctl() kvm: Pass CPUState to kvm_arch_* cpu: Move kvm_fd into CPUState qdev-properties.c: Separate core from the code used only by qemu-system-* qdev: Coding style fixes cpu: Introduce CPUListState struct target-alpha: Add support for -cpu ? target-alpha: Turn CPU definitions into subclasses target-alpha: Avoid leaking the alarm timer over reset alpha: Pass AlphaCPU array to Typhoon target-alpha: Let cpu_alpha_init() return AlphaCPU
This commit is contained in:
commit
4de63460ca
42 changed files with 1224 additions and 867 deletions
|
@ -181,6 +181,7 @@ common-obj-y += bt.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o
|
|||
common-obj-y += bt-hci-csr.o
|
||||
common-obj-y += msmouse.o ps2.o
|
||||
common-obj-y += qdev.o qdev-properties.o qdev-monitor.o
|
||||
common-obj-y += qdev-properties-system.o
|
||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
||||
|
||||
# xen backend driver support
|
||||
|
|
|
@ -50,7 +50,7 @@ static void clipper_init(QEMUMachineInitArgs *args)
|
|||
const char *kernel_filename = args->kernel_filename;
|
||||
const char *kernel_cmdline = args->kernel_cmdline;
|
||||
const char *initrd_filename = args->initrd_filename;
|
||||
CPUAlphaState *cpus[4];
|
||||
AlphaCPU *cpus[4];
|
||||
PCIBus *pci_bus;
|
||||
ISABus *isa_bus;
|
||||
qemu_irq rtc_irq;
|
||||
|
@ -62,12 +62,12 @@ static void clipper_init(QEMUMachineInitArgs *args)
|
|||
/* Create up to 4 cpus. */
|
||||
memset(cpus, 0, sizeof(cpus));
|
||||
for (i = 0; i < smp_cpus; ++i) {
|
||||
cpus[i] = cpu_init(cpu_model ? cpu_model : "ev67");
|
||||
cpus[i] = cpu_alpha_init(cpu_model ? cpu_model : "ev67");
|
||||
}
|
||||
|
||||
cpus[0]->trap_arg0 = ram_size;
|
||||
cpus[0]->trap_arg1 = 0;
|
||||
cpus[0]->trap_arg2 = smp_cpus;
|
||||
cpus[0]->env.trap_arg0 = ram_size;
|
||||
cpus[0]->env.trap_arg1 = 0;
|
||||
cpus[0]->env.trap_arg2 = smp_cpus;
|
||||
|
||||
/* Init the chipset. */
|
||||
pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus,
|
||||
|
@ -119,9 +119,9 @@ static void clipper_init(QEMUMachineInitArgs *args)
|
|||
|
||||
/* Start all cpus at the PALcode RESET entry point. */
|
||||
for (i = 0; i < smp_cpus; ++i) {
|
||||
cpus[i]->pal_mode = 1;
|
||||
cpus[i]->pc = palcode_entry;
|
||||
cpus[i]->palbr = palcode_entry;
|
||||
cpus[i]->env.pal_mode = 1;
|
||||
cpus[i]->env.pc = palcode_entry;
|
||||
cpus[i]->env.palbr = palcode_entry;
|
||||
}
|
||||
|
||||
/* Load a kernel. */
|
||||
|
@ -136,7 +136,7 @@ static void clipper_init(QEMUMachineInitArgs *args)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
cpus[0]->trap_arg1 = kernel_entry;
|
||||
cpus[0]->env.trap_arg1 = kernel_entry;
|
||||
|
||||
param_offset = kernel_low - 0x6000;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include "irq.h"
|
||||
|
||||
|
||||
PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, CPUAlphaState *[4],
|
||||
PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, AlphaCPU *[4],
|
||||
pci_map_irq_fn);
|
||||
|
||||
/* alpha_pci.c. */
|
||||
|
|
|
@ -23,7 +23,7 @@ typedef struct TyphoonCchip {
|
|||
uint64_t drir;
|
||||
uint64_t dim[4];
|
||||
uint32_t iic[4];
|
||||
CPUAlphaState *cpu[4];
|
||||
AlphaCPU *cpu[4];
|
||||
} TyphoonCchip;
|
||||
|
||||
typedef struct TyphoonWindow {
|
||||
|
@ -58,10 +58,11 @@ typedef struct TyphoonState {
|
|||
} TyphoonState;
|
||||
|
||||
/* Called when one of DRIR or DIM changes. */
|
||||
static void cpu_irq_change(CPUAlphaState *env, uint64_t req)
|
||||
static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
|
||||
{
|
||||
/* If there are any non-masked interrupts, tell the cpu. */
|
||||
if (env) {
|
||||
if (cpu != NULL) {
|
||||
CPUAlphaState *env = &cpu->env;
|
||||
if (req) {
|
||||
cpu_interrupt(env, CPU_INTERRUPT_HARD);
|
||||
} else {
|
||||
|
@ -353,8 +354,9 @@ static void cchip_write(void *opaque, hwaddr addr,
|
|||
if ((newval ^ oldval) & 0xff0) {
|
||||
int i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
CPUAlphaState *env = s->cchip.cpu[i];
|
||||
if (env) {
|
||||
AlphaCPU *cpu = s->cchip.cpu[i];
|
||||
if (cpu != NULL) {
|
||||
CPUAlphaState *env = &cpu->env;
|
||||
/* IPI can be either cleared or set by the write. */
|
||||
if (newval & (1 << (i + 8))) {
|
||||
cpu_interrupt(env, CPU_INTERRUPT_SMP);
|
||||
|
@ -661,8 +663,8 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level)
|
|||
|
||||
/* Deliver the interrupt to each CPU, considering each CPU's IIC. */
|
||||
for (i = 0; i < 4; ++i) {
|
||||
CPUAlphaState *env = s->cchip.cpu[i];
|
||||
if (env) {
|
||||
AlphaCPU *cpu = s->cchip.cpu[i];
|
||||
if (cpu != NULL) {
|
||||
uint32_t iic = s->cchip.iic[i];
|
||||
|
||||
/* ??? The verbage in Section 10.2.2.10 isn't 100% clear.
|
||||
|
@ -681,7 +683,7 @@ static void typhoon_set_timer_irq(void *opaque, int irq, int level)
|
|||
/* Set the ITI bit for this cpu. */
|
||||
s->cchip.misc |= 1 << (i + 4);
|
||||
/* And signal the interrupt. */
|
||||
cpu_interrupt(env, CPU_INTERRUPT_TIMER);
|
||||
cpu_interrupt(&cpu->env, CPU_INTERRUPT_TIMER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -694,12 +696,12 @@ static void typhoon_alarm_timer(void *opaque)
|
|||
|
||||
/* Set the ITI bit for this cpu. */
|
||||
s->cchip.misc |= 1 << (cpu + 4);
|
||||
cpu_interrupt(s->cchip.cpu[cpu], CPU_INTERRUPT_TIMER);
|
||||
cpu_interrupt(&s->cchip.cpu[cpu]->env, CPU_INTERRUPT_TIMER);
|
||||
}
|
||||
|
||||
PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
|
||||
qemu_irq *p_rtc_irq,
|
||||
CPUAlphaState *cpus[4], pci_map_irq_fn sys_map_irq)
|
||||
AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq)
|
||||
{
|
||||
const uint64_t MB = 1024 * 1024;
|
||||
const uint64_t GB = 1024 * MB;
|
||||
|
@ -719,10 +721,10 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
|
|||
|
||||
/* Remember the CPUs so that we can deliver interrupts to them. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
CPUAlphaState *env = cpus[i];
|
||||
s->cchip.cpu[i] = env;
|
||||
if (env) {
|
||||
env->alarm_timer = qemu_new_timer_ns(rtc_clock,
|
||||
AlphaCPU *cpu = cpus[i];
|
||||
s->cchip.cpu[i] = cpu;
|
||||
if (cpu != NULL) {
|
||||
cpu->alarm_timer = qemu_new_timer_ns(rtc_clock,
|
||||
typhoon_alarm_timer,
|
||||
(void *)((uintptr_t)s + i));
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ static void kvm_apic_enable_tpr_reporting(APICCommonState *s, bool enable)
|
|||
.enabled = enable
|
||||
};
|
||||
|
||||
kvm_vcpu_ioctl(&s->cpu->env, KVM_TPR_ACCESS_REPORTING, &ctl);
|
||||
kvm_vcpu_ioctl(CPU(s->cpu), KVM_TPR_ACCESS_REPORTING, &ctl);
|
||||
}
|
||||
|
||||
static void kvm_apic_vapic_base_update(APICCommonState *s)
|
||||
|
@ -114,7 +114,7 @@ static void kvm_apic_vapic_base_update(APICCommonState *s)
|
|||
};
|
||||
int ret;
|
||||
|
||||
ret = kvm_vcpu_ioctl(&s->cpu->env, KVM_SET_VAPIC_ADDR, &vapid_addr);
|
||||
ret = kvm_vcpu_ioctl(CPU(s->cpu), KVM_SET_VAPIC_ADDR, &vapid_addr);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "KVM: setting VAPIC address failed (%s)\n",
|
||||
strerror(-ret));
|
||||
|
@ -125,15 +125,15 @@ static void kvm_apic_vapic_base_update(APICCommonState *s)
|
|||
static void do_inject_external_nmi(void *data)
|
||||
{
|
||||
APICCommonState *s = data;
|
||||
CPUX86State *env = &s->cpu->env;
|
||||
CPUState *cpu = CPU(s->cpu);
|
||||
uint32_t lvt;
|
||||
int ret;
|
||||
|
||||
cpu_synchronize_state(env);
|
||||
cpu_synchronize_state(&s->cpu->env);
|
||||
|
||||
lvt = s->lvt[APIC_LVT_LINT1];
|
||||
if (!(lvt & APIC_LVT_MASKED) && ((lvt >> 8) & 7) == APIC_DM_NMI) {
|
||||
ret = kvm_vcpu_ioctl(env, KVM_NMI);
|
||||
ret = kvm_vcpu_ioctl(cpu, KVM_NMI);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "KVM: injection failed, NMI lost (%s)\n",
|
||||
strerror(-ret));
|
||||
|
|
|
@ -76,7 +76,7 @@ static void kvmclock_vm_state_change(void *opaque, int running,
|
|||
return;
|
||||
}
|
||||
for (penv = first_cpu; penv != NULL; penv = penv->next_cpu) {
|
||||
ret = kvm_vcpu_ioctl(penv, KVM_KVMCLOCK_CTRL, 0);
|
||||
ret = kvm_vcpu_ioctl(ENV_GET_CPU(penv), KVM_KVMCLOCK_CTRL, 0);
|
||||
if (ret) {
|
||||
if (ret != -EINVAL) {
|
||||
fprintf(stderr, "%s: %s\n", __func__, strerror(-ret));
|
||||
|
|
128
hw/ppc.c
128
hw/ppc.c
|
@ -50,8 +50,9 @@
|
|||
static void cpu_ppc_tb_stop (CPUPPCState *env);
|
||||
static void cpu_ppc_tb_start (CPUPPCState *env);
|
||||
|
||||
void ppc_set_irq(CPUPPCState *env, int n_IRQ, int level)
|
||||
void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
unsigned int old_pending = env->pending_interrupts;
|
||||
|
||||
if (level) {
|
||||
|
@ -65,7 +66,7 @@ void ppc_set_irq(CPUPPCState *env, int n_IRQ, int level)
|
|||
|
||||
if (old_pending != env->pending_interrupts) {
|
||||
#ifdef CONFIG_KVM
|
||||
kvmppc_set_interrupt(env, n_IRQ, level);
|
||||
kvmppc_set_interrupt(cpu, n_IRQ, level);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -100,13 +101,13 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
|
|||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the external IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
|
||||
break;
|
||||
case PPC6xx_INPUT_SMI:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the SMI IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_SMI, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_SMI, level);
|
||||
break;
|
||||
case PPC6xx_INPUT_MCP:
|
||||
/* Negative edge sensitive */
|
||||
|
@ -116,7 +117,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
|
|||
if (cur_level == 1 && level == 0) {
|
||||
LOG_IRQ("%s: raise machine check state\n",
|
||||
__func__);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
|
||||
}
|
||||
break;
|
||||
case PPC6xx_INPUT_CKSTP_IN:
|
||||
|
@ -138,7 +139,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
|
|||
case PPC6xx_INPUT_SRESET:
|
||||
LOG_IRQ("%s: set the RESET IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
|
||||
break;
|
||||
default:
|
||||
/* Unknown pin - do nothing */
|
||||
|
@ -178,13 +179,13 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
|
|||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the external IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
|
||||
break;
|
||||
case PPC970_INPUT_THINT:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the SMI IRQ state to %d\n", __func__,
|
||||
level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_THERM, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_THERM, level);
|
||||
break;
|
||||
case PPC970_INPUT_MCP:
|
||||
/* Negative edge sensitive */
|
||||
|
@ -194,7 +195,7 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
|
|||
if (cur_level == 1 && level == 0) {
|
||||
LOG_IRQ("%s: raise machine check state\n",
|
||||
__func__);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_MCK, 1);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_MCK, 1);
|
||||
}
|
||||
break;
|
||||
case PPC970_INPUT_CKSTP:
|
||||
|
@ -218,7 +219,7 @@ static void ppc970_set_irq(void *opaque, int pin, int level)
|
|||
case PPC970_INPUT_SRESET:
|
||||
LOG_IRQ("%s: set the RESET IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_RESET, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_RESET, level);
|
||||
break;
|
||||
case PPC970_INPUT_TBEN:
|
||||
LOG_IRQ("%s: set the TBEN state to %d\n", __func__,
|
||||
|
@ -259,7 +260,7 @@ static void power7_set_irq(void *opaque, int pin, int level)
|
|||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the external IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
|
||||
break;
|
||||
default:
|
||||
/* Unknown pin - do nothing */
|
||||
|
@ -319,13 +320,13 @@ static void ppc40x_set_irq(void *opaque, int pin, int level)
|
|||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the critical IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
|
||||
break;
|
||||
case PPC40x_INPUT_INT:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the external IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
|
||||
break;
|
||||
case PPC40x_INPUT_HALT:
|
||||
/* Level sensitive - active low */
|
||||
|
@ -342,7 +343,7 @@ static void ppc40x_set_irq(void *opaque, int pin, int level)
|
|||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the debug pin state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level);
|
||||
break;
|
||||
default:
|
||||
/* Unknown pin - do nothing */
|
||||
|
@ -387,26 +388,26 @@ static void ppce500_set_irq(void *opaque, int pin, int level)
|
|||
case PPCE500_INPUT_RESET_CORE:
|
||||
if (level) {
|
||||
LOG_IRQ("%s: reset the PowerPC core\n", __func__);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_MCK, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_MCK, level);
|
||||
}
|
||||
break;
|
||||
case PPCE500_INPUT_CINT:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the critical IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_CEXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_CEXT, level);
|
||||
break;
|
||||
case PPCE500_INPUT_INT:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the core IRQ state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_EXT, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_EXT, level);
|
||||
break;
|
||||
case PPCE500_INPUT_DEBUG:
|
||||
/* Level sensitive - active high */
|
||||
LOG_IRQ("%s: set the debug pin state to %d\n",
|
||||
__func__, level);
|
||||
ppc_set_irq(env, PPC_INTERRUPT_DEBUG, level);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_DEBUG, level);
|
||||
break;
|
||||
default:
|
||||
/* Unknown pin - do nothing */
|
||||
|
@ -643,26 +644,27 @@ uint64_t cpu_ppc_load_purr (CPUPPCState *env)
|
|||
/* When decrementer expires,
|
||||
* all we need to do is generate or queue a CPU exception
|
||||
*/
|
||||
static inline void cpu_ppc_decr_excp(CPUPPCState *env)
|
||||
static inline void cpu_ppc_decr_excp(PowerPCCPU *cpu)
|
||||
{
|
||||
/* Raise it */
|
||||
LOG_TB("raise decrementer exception\n");
|
||||
ppc_set_irq(env, PPC_INTERRUPT_DECR, 1);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_DECR, 1);
|
||||
}
|
||||
|
||||
static inline void cpu_ppc_hdecr_excp(CPUPPCState *env)
|
||||
static inline void cpu_ppc_hdecr_excp(PowerPCCPU *cpu)
|
||||
{
|
||||
/* Raise it */
|
||||
LOG_TB("raise decrementer exception\n");
|
||||
ppc_set_irq(env, PPC_INTERRUPT_HDECR, 1);
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 1);
|
||||
}
|
||||
|
||||
static void __cpu_ppc_store_decr (CPUPPCState *env, uint64_t *nextp,
|
||||
struct QEMUTimer *timer,
|
||||
void (*raise_excp)(CPUPPCState *),
|
||||
uint32_t decr, uint32_t value,
|
||||
int is_excp)
|
||||
static void __cpu_ppc_store_decr(PowerPCCPU *cpu, uint64_t *nextp,
|
||||
struct QEMUTimer *timer,
|
||||
void (*raise_excp)(PowerPCCPU *),
|
||||
uint32_t decr, uint32_t value,
|
||||
int is_excp)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
uint64_t now, next;
|
||||
|
||||
|
@ -692,53 +694,61 @@ static void __cpu_ppc_store_decr (CPUPPCState *env, uint64_t *nextp,
|
|||
if ((tb_env->flags & PPC_DECR_UNDERFLOW_TRIGGERED)
|
||||
&& (value & 0x80000000)
|
||||
&& !(decr & 0x80000000)) {
|
||||
(*raise_excp)(env);
|
||||
(*raise_excp)(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _cpu_ppc_store_decr(CPUPPCState *env, uint32_t decr,
|
||||
static inline void _cpu_ppc_store_decr(PowerPCCPU *cpu, uint32_t decr,
|
||||
uint32_t value, int is_excp)
|
||||
{
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
ppc_tb_t *tb_env = cpu->env.tb_env;
|
||||
|
||||
__cpu_ppc_store_decr(env, &tb_env->decr_next, tb_env->decr_timer,
|
||||
__cpu_ppc_store_decr(cpu, &tb_env->decr_next, tb_env->decr_timer,
|
||||
&cpu_ppc_decr_excp, decr, value, is_excp);
|
||||
}
|
||||
|
||||
void cpu_ppc_store_decr (CPUPPCState *env, uint32_t value)
|
||||
{
|
||||
_cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
|
||||
_cpu_ppc_store_decr(cpu, cpu_ppc_load_decr(env), value, 0);
|
||||
}
|
||||
|
||||
static void cpu_ppc_decr_cb (void *opaque)
|
||||
static void cpu_ppc_decr_cb(void *opaque)
|
||||
{
|
||||
_cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
|
||||
PowerPCCPU *cpu = opaque;
|
||||
|
||||
_cpu_ppc_store_decr(cpu, 0x00000000, 0xFFFFFFFF, 1);
|
||||
}
|
||||
|
||||
static inline void _cpu_ppc_store_hdecr(CPUPPCState *env, uint32_t hdecr,
|
||||
static inline void _cpu_ppc_store_hdecr(PowerPCCPU *cpu, uint32_t hdecr,
|
||||
uint32_t value, int is_excp)
|
||||
{
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
ppc_tb_t *tb_env = cpu->env.tb_env;
|
||||
|
||||
if (tb_env->hdecr_timer != NULL) {
|
||||
__cpu_ppc_store_decr(env, &tb_env->hdecr_next, tb_env->hdecr_timer,
|
||||
__cpu_ppc_store_decr(cpu, &tb_env->hdecr_next, tb_env->hdecr_timer,
|
||||
&cpu_ppc_hdecr_excp, hdecr, value, is_excp);
|
||||
}
|
||||
}
|
||||
|
||||
void cpu_ppc_store_hdecr (CPUPPCState *env, uint32_t value)
|
||||
{
|
||||
_cpu_ppc_store_hdecr(env, cpu_ppc_load_hdecr(env), value, 0);
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
|
||||
_cpu_ppc_store_hdecr(cpu, cpu_ppc_load_hdecr(env), value, 0);
|
||||
}
|
||||
|
||||
static void cpu_ppc_hdecr_cb (void *opaque)
|
||||
static void cpu_ppc_hdecr_cb(void *opaque)
|
||||
{
|
||||
_cpu_ppc_store_hdecr(opaque, 0x00000000, 0xFFFFFFFF, 1);
|
||||
PowerPCCPU *cpu = opaque;
|
||||
|
||||
_cpu_ppc_store_hdecr(cpu, 0x00000000, 0xFFFFFFFF, 1);
|
||||
}
|
||||
|
||||
static void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value)
|
||||
static void cpu_ppc_store_purr(PowerPCCPU *cpu, uint64_t value)
|
||||
{
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
ppc_tb_t *tb_env = cpu->env.tb_env;
|
||||
|
||||
tb_env->purr_load = value;
|
||||
tb_env->purr_start = qemu_get_clock_ns(vm_clock);
|
||||
|
@ -747,6 +757,7 @@ static void cpu_ppc_store_purr(CPUPPCState *env, uint64_t value)
|
|||
static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
|
||||
{
|
||||
CPUPPCState *env = opaque;
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
|
||||
tb_env->tb_freq = freq;
|
||||
|
@ -755,25 +766,27 @@ static void cpu_ppc_set_tb_clk (void *opaque, uint32_t freq)
|
|||
* if a decrementer exception is pending when it enables msr_ee at startup,
|
||||
* it's not ready to handle it...
|
||||
*/
|
||||
_cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
||||
_cpu_ppc_store_hdecr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
||||
cpu_ppc_store_purr(env, 0x0000000000000000ULL);
|
||||
_cpu_ppc_store_decr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
||||
_cpu_ppc_store_hdecr(cpu, 0xFFFFFFFF, 0xFFFFFFFF, 0);
|
||||
cpu_ppc_store_purr(cpu, 0x0000000000000000ULL);
|
||||
}
|
||||
|
||||
/* Set up (once) timebase frequency (in Hz) */
|
||||
clk_setup_cb cpu_ppc_tb_init (CPUPPCState *env, uint32_t freq)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
ppc_tb_t *tb_env;
|
||||
|
||||
tb_env = g_malloc0(sizeof(ppc_tb_t));
|
||||
env->tb_env = tb_env;
|
||||
tb_env->flags = PPC_DECR_UNDERFLOW_TRIGGERED;
|
||||
/* Create new timer */
|
||||
tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, env);
|
||||
tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_decr_cb, cpu);
|
||||
if (0) {
|
||||
/* XXX: find a suitable condition to enable the hypervisor decrementer
|
||||
*/
|
||||
tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb, env);
|
||||
tb_env->hdecr_timer = qemu_new_timer_ns(vm_clock, &cpu_ppc_hdecr_cb,
|
||||
cpu);
|
||||
} else {
|
||||
tb_env->hdecr_timer = NULL;
|
||||
}
|
||||
|
@ -829,12 +842,14 @@ struct ppc40x_timer_t {
|
|||
/* Fixed interval timer */
|
||||
static void cpu_4xx_fit_cb (void *opaque)
|
||||
{
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
ppc_tb_t *tb_env;
|
||||
ppc40x_timer_t *ppc40x_timer;
|
||||
uint64_t now, next;
|
||||
|
||||
env = opaque;
|
||||
cpu = ppc_env_get_cpu(env);
|
||||
tb_env = env->tb_env;
|
||||
ppc40x_timer = tb_env->opaque;
|
||||
now = qemu_get_clock_ns(vm_clock);
|
||||
|
@ -860,8 +875,9 @@ static void cpu_4xx_fit_cb (void *opaque)
|
|||
next++;
|
||||
qemu_mod_timer(ppc40x_timer->fit_timer, next);
|
||||
env->spr[SPR_40x_TSR] |= 1 << 26;
|
||||
if ((env->spr[SPR_40x_TCR] >> 23) & 0x1)
|
||||
ppc_set_irq(env, PPC_INTERRUPT_FIT, 1);
|
||||
if ((env->spr[SPR_40x_TCR] >> 23) & 0x1) {
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_FIT, 1);
|
||||
}
|
||||
LOG_TB("%s: ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx "\n", __func__,
|
||||
(int)((env->spr[SPR_40x_TCR] >> 23) & 0x1),
|
||||
env->spr[SPR_40x_TCR], env->spr[SPR_40x_TSR]);
|
||||
|
@ -897,16 +913,19 @@ static void start_stop_pit (CPUPPCState *env, ppc_tb_t *tb_env, int is_excp)
|
|||
|
||||
static void cpu_4xx_pit_cb (void *opaque)
|
||||
{
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
ppc_tb_t *tb_env;
|
||||
ppc40x_timer_t *ppc40x_timer;
|
||||
|
||||
env = opaque;
|
||||
cpu = ppc_env_get_cpu(env);
|
||||
tb_env = env->tb_env;
|
||||
ppc40x_timer = tb_env->opaque;
|
||||
env->spr[SPR_40x_TSR] |= 1 << 27;
|
||||
if ((env->spr[SPR_40x_TCR] >> 26) & 0x1)
|
||||
ppc_set_irq(env, ppc40x_timer->decr_excp, 1);
|
||||
if ((env->spr[SPR_40x_TCR] >> 26) & 0x1) {
|
||||
ppc_set_irq(cpu, ppc40x_timer->decr_excp, 1);
|
||||
}
|
||||
start_stop_pit(env, tb_env, 1);
|
||||
LOG_TB("%s: ar %d ir %d TCR " TARGET_FMT_lx " TSR " TARGET_FMT_lx " "
|
||||
"%016" PRIx64 "\n", __func__,
|
||||
|
@ -919,12 +938,14 @@ static void cpu_4xx_pit_cb (void *opaque)
|
|||
/* Watchdog timer */
|
||||
static void cpu_4xx_wdt_cb (void *opaque)
|
||||
{
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
ppc_tb_t *tb_env;
|
||||
ppc40x_timer_t *ppc40x_timer;
|
||||
uint64_t now, next;
|
||||
|
||||
env = opaque;
|
||||
cpu = ppc_env_get_cpu(env);
|
||||
tb_env = env->tb_env;
|
||||
ppc40x_timer = tb_env->opaque;
|
||||
now = qemu_get_clock_ns(vm_clock);
|
||||
|
@ -961,8 +982,9 @@ static void cpu_4xx_wdt_cb (void *opaque)
|
|||
qemu_mod_timer(ppc40x_timer->wdt_timer, next);
|
||||
ppc40x_timer->wdt_next = next;
|
||||
env->spr[SPR_40x_TSR] |= 1 << 30;
|
||||
if ((env->spr[SPR_40x_TCR] >> 27) & 0x1)
|
||||
ppc_set_irq(env, PPC_INTERRUPT_WDT, 1);
|
||||
if ((env->spr[SPR_40x_TCR] >> 27) & 0x1) {
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_WDT, 1);
|
||||
}
|
||||
break;
|
||||
case 0x3:
|
||||
env->spr[SPR_40x_TSR] &= ~0x30000000;
|
||||
|
|
4
hw/ppc.h
4
hw/ppc.h
|
@ -1,7 +1,7 @@
|
|||
#ifndef HW_PPC_H
|
||||
#define HW_PPC_H 1
|
||||
|
||||
void ppc_set_irq (CPUPPCState *env, int n_IRQ, int level);
|
||||
void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level);
|
||||
|
||||
/* PowerPC hardware exceptions management helpers */
|
||||
typedef void (*clk_setup_cb)(void *opaque, uint32_t freq);
|
||||
|
@ -92,6 +92,6 @@ enum {
|
|||
#define PPC_SERIAL_MM_BAUDBASE 399193
|
||||
|
||||
/* ppc_booke.c */
|
||||
void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags);
|
||||
void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -496,7 +496,7 @@ void ppce500_init(PPCE500Params *params)
|
|||
env->mpic_cpu_base = MPC8544_CCSRBAR_BASE +
|
||||
MPC8544_MPIC_REGS_OFFSET + 0x20000;
|
||||
|
||||
ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500);
|
||||
ppc_booke_timers_init(cpu, 400000000, PPC_TIMER_E500);
|
||||
|
||||
/* Register reset handler */
|
||||
if (!i) {
|
||||
|
|
|
@ -2111,12 +2111,14 @@ CPUPPCState *ppc405cr_init(MemoryRegion *address_space_mem,
|
|||
{
|
||||
clk_setup_t clk_setup[PPC405CR_CLK_NB];
|
||||
qemu_irq dma_irqs[4];
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
qemu_irq *pic, *irqs;
|
||||
|
||||
memset(clk_setup, 0, sizeof(clk_setup));
|
||||
env = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
|
||||
cpu = ppc4xx_init("405cr", &clk_setup[PPC405CR_CPU_CLK],
|
||||
&clk_setup[PPC405CR_TMR_CLK], sysclk);
|
||||
env = &cpu->env;
|
||||
/* Memory mapped devices registers */
|
||||
/* PLB arbitrer */
|
||||
ppc4xx_plb_init(env);
|
||||
|
@ -2460,13 +2462,15 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
|
|||
{
|
||||
clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup;
|
||||
qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4];
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
qemu_irq *pic, *irqs;
|
||||
|
||||
memset(clk_setup, 0, sizeof(clk_setup));
|
||||
/* init CPUs */
|
||||
env = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
|
||||
cpu = ppc4xx_init("405ep", &clk_setup[PPC405EP_CPU_CLK],
|
||||
&tlb_clk_setup, sysclk);
|
||||
env = &cpu->env;
|
||||
clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb;
|
||||
clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque;
|
||||
/* Internal devices init */
|
||||
|
@ -2478,7 +2482,7 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
|
|||
/* OBP arbitrer */
|
||||
ppc4xx_opba_init(0xef600600);
|
||||
/* Initialize timers */
|
||||
ppc_booke_timers_init(env, sysclk, 0);
|
||||
ppc_booke_timers_init(cpu, sysclk, 0);
|
||||
/* Universal interrupt controller */
|
||||
irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
|
||||
irqs[PPCUIC_OUTPUT_INT] =
|
||||
|
|
|
@ -195,7 +195,7 @@ static void bamboo_init(QEMUMachineInitArgs *args)
|
|||
env = &cpu->env;
|
||||
|
||||
qemu_register_reset(main_cpu_reset, cpu);
|
||||
ppc_booke_timers_init(env, 400000000, 0);
|
||||
ppc_booke_timers_init(cpu, 400000000, 0);
|
||||
ppc_dcr_init(env, NULL, NULL);
|
||||
|
||||
/* interrupt controller */
|
||||
|
|
|
@ -28,9 +28,9 @@
|
|||
#include "pci/pci.h"
|
||||
|
||||
/* PowerPC 4xx core initialization */
|
||||
CPUPPCState *ppc4xx_init (const char *cpu_model,
|
||||
clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
|
||||
uint32_t sysclk);
|
||||
PowerPCCPU *ppc4xx_init(const char *cpu_model,
|
||||
clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
|
||||
uint32_t sysclk);
|
||||
|
||||
/* PowerPC 4xx universal interrupt controller */
|
||||
enum {
|
||||
|
|
|
@ -47,9 +47,9 @@ static void ppc4xx_reset(void *opaque)
|
|||
|
||||
/*****************************************************************************/
|
||||
/* Generic PowerPC 4xx processor instantiation */
|
||||
CPUPPCState *ppc4xx_init (const char *cpu_model,
|
||||
clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
|
||||
uint32_t sysclk)
|
||||
PowerPCCPU *ppc4xx_init(const char *cpu_model,
|
||||
clk_setup_t *cpu_clk, clk_setup_t *tb_clk,
|
||||
uint32_t sysclk)
|
||||
{
|
||||
PowerPCCPU *cpu;
|
||||
CPUPPCState *env;
|
||||
|
@ -72,7 +72,7 @@ CPUPPCState *ppc4xx_init (const char *cpu_model,
|
|||
/* Register qemu callbacks */
|
||||
qemu_register_reset(ppc4xx_reset, cpu);
|
||||
|
||||
return env;
|
||||
return cpu;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -71,17 +71,19 @@ struct booke_timer_t {
|
|||
uint32_t flags;
|
||||
};
|
||||
|
||||
static void booke_update_irq(CPUPPCState *env)
|
||||
static void booke_update_irq(PowerPCCPU *cpu)
|
||||
{
|
||||
ppc_set_irq(env, PPC_INTERRUPT_DECR,
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_DECR,
|
||||
(env->spr[SPR_BOOKE_TSR] & TSR_DIS
|
||||
&& env->spr[SPR_BOOKE_TCR] & TCR_DIE));
|
||||
|
||||
ppc_set_irq(env, PPC_INTERRUPT_WDT,
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_WDT,
|
||||
(env->spr[SPR_BOOKE_TSR] & TSR_WIS
|
||||
&& env->spr[SPR_BOOKE_TCR] & TCR_WIE));
|
||||
|
||||
ppc_set_irq(env, PPC_INTERRUPT_FIT,
|
||||
ppc_set_irq(cpu, PPC_INTERRUPT_FIT,
|
||||
(env->spr[SPR_BOOKE_TSR] & TSR_FIS
|
||||
&& env->spr[SPR_BOOKE_TCR] & TCR_FIE));
|
||||
}
|
||||
|
@ -153,10 +155,11 @@ static void booke_update_fixed_timer(CPUPPCState *env,
|
|||
|
||||
static void booke_decr_cb(void *opaque)
|
||||
{
|
||||
CPUPPCState *env = opaque;
|
||||
PowerPCCPU *cpu = opaque;
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
env->spr[SPR_BOOKE_TSR] |= TSR_DIS;
|
||||
booke_update_irq(env);
|
||||
booke_update_irq(cpu);
|
||||
|
||||
if (env->spr[SPR_BOOKE_TCR] & TCR_ARE) {
|
||||
/* Auto Reload */
|
||||
|
@ -166,16 +169,16 @@ static void booke_decr_cb(void *opaque)
|
|||
|
||||
static void booke_fit_cb(void *opaque)
|
||||
{
|
||||
CPUPPCState *env;
|
||||
PowerPCCPU *cpu = opaque;
|
||||
CPUPPCState *env = &cpu->env;
|
||||
ppc_tb_t *tb_env;
|
||||
booke_timer_t *booke_timer;
|
||||
|
||||
env = opaque;
|
||||
tb_env = env->tb_env;
|
||||
booke_timer = tb_env->opaque;
|
||||
env->spr[SPR_BOOKE_TSR] |= TSR_FIS;
|
||||
|
||||
booke_update_irq(env);
|
||||
booke_update_irq(cpu);
|
||||
|
||||
booke_update_fixed_timer(env,
|
||||
booke_get_fit_target(env, tb_env),
|
||||
|
@ -185,17 +188,17 @@ static void booke_fit_cb(void *opaque)
|
|||
|
||||
static void booke_wdt_cb(void *opaque)
|
||||
{
|
||||
CPUPPCState *env;
|
||||
PowerPCCPU *cpu = opaque;
|
||||
CPUPPCState *env = &cpu->env;
|
||||
ppc_tb_t *tb_env;
|
||||
booke_timer_t *booke_timer;
|
||||
|
||||
env = opaque;
|
||||
tb_env = env->tb_env;
|
||||
booke_timer = tb_env->opaque;
|
||||
|
||||
/* TODO: There's lots of complicated stuff to do here */
|
||||
|
||||
booke_update_irq(env);
|
||||
booke_update_irq(cpu);
|
||||
|
||||
booke_update_fixed_timer(env,
|
||||
booke_get_wdt_target(env, tb_env),
|
||||
|
@ -205,19 +208,22 @@ static void booke_wdt_cb(void *opaque)
|
|||
|
||||
void store_booke_tsr(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
|
||||
env->spr[SPR_BOOKE_TSR] &= ~val;
|
||||
booke_update_irq(env);
|
||||
booke_update_irq(cpu);
|
||||
}
|
||||
|
||||
void store_booke_tcr(CPUPPCState *env, target_ulong val)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
ppc_tb_t *tb_env = env->tb_env;
|
||||
booke_timer_t *booke_timer = tb_env->opaque;
|
||||
|
||||
tb_env = env->tb_env;
|
||||
env->spr[SPR_BOOKE_TCR] = val;
|
||||
|
||||
booke_update_irq(env);
|
||||
booke_update_irq(cpu);
|
||||
|
||||
booke_update_fixed_timer(env,
|
||||
booke_get_fit_target(env, tb_env),
|
||||
|
@ -231,7 +237,7 @@ void store_booke_tcr(CPUPPCState *env, target_ulong val)
|
|||
|
||||
}
|
||||
|
||||
void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags)
|
||||
void ppc_booke_timers_init(PowerPCCPU *cpu, uint32_t freq, uint32_t flags)
|
||||
{
|
||||
ppc_tb_t *tb_env;
|
||||
booke_timer_t *booke_timer;
|
||||
|
@ -239,16 +245,16 @@ void ppc_booke_timers_init(CPUPPCState *env, uint32_t freq, uint32_t flags)
|
|||
tb_env = g_malloc0(sizeof(ppc_tb_t));
|
||||
booke_timer = g_malloc0(sizeof(booke_timer_t));
|
||||
|
||||
env->tb_env = tb_env;
|
||||
cpu->env.tb_env = tb_env;
|
||||
tb_env->flags = flags | PPC_TIMER_BOOKE | PPC_DECR_ZERO_TRIGGERED;
|
||||
|
||||
tb_env->tb_freq = freq;
|
||||
tb_env->decr_freq = freq;
|
||||
tb_env->opaque = booke_timer;
|
||||
tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &booke_decr_cb, env);
|
||||
tb_env->decr_timer = qemu_new_timer_ns(vm_clock, &booke_decr_cb, cpu);
|
||||
|
||||
booke_timer->fit_timer =
|
||||
qemu_new_timer_ns(vm_clock, &booke_fit_cb, env);
|
||||
qemu_new_timer_ns(vm_clock, &booke_fit_cb, cpu);
|
||||
booke_timer->wdt_timer =
|
||||
qemu_new_timer_ns(vm_clock, &booke_wdt_cb, env);
|
||||
qemu_new_timer_ns(vm_clock, &booke_wdt_cb, cpu);
|
||||
}
|
||||
|
|
358
hw/qdev-properties-system.c
Normal file
358
hw/qdev-properties-system.c
Normal file
|
@ -0,0 +1,358 @@
|
|||
/*
|
||||
* qdev property parsing and global properties
|
||||
* (parts specific for qemu-system-*)
|
||||
*
|
||||
* This file is based on code from hw/qdev-properties.c from
|
||||
* commit 074a86fccd185616469dfcdc0e157f438aebba18,
|
||||
* Copyright (c) Gerd Hoffmann <kraxel@redhat.com> and other contributors.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "net/net.h"
|
||||
#include "qdev.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "hw/block-common.h"
|
||||
#include "net/hub.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "char/char.h"
|
||||
|
||||
static void get_pointer(Object *obj, Visitor *v, Property *prop,
|
||||
const char *(*print)(void *ptr),
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
void **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
char *p;
|
||||
|
||||
p = (char *) (*ptr ? print(*ptr) : "");
|
||||
visit_type_str(v, &p, name, errp);
|
||||
}
|
||||
|
||||
static void set_pointer(Object *obj, Visitor *v, Property *prop,
|
||||
int (*parse)(DeviceState *dev, const char *str,
|
||||
void **ptr),
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Error *local_err = NULL;
|
||||
void **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
char *str;
|
||||
int ret;
|
||||
|
||||
if (dev->state != DEV_STATE_CREATED) {
|
||||
error_set(errp, QERR_PERMISSION_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
visit_type_str(v, &str, name, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
if (!*str) {
|
||||
g_free(str);
|
||||
*ptr = NULL;
|
||||
return;
|
||||
}
|
||||
ret = parse(dev, str, ptr);
|
||||
error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
/* --- drive --- */
|
||||
|
||||
static int parse_drive(DeviceState *dev, const char *str, void **ptr)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
|
||||
bs = bdrv_find(str);
|
||||
if (bs == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
if (bdrv_attach_dev(bs, dev) < 0) {
|
||||
return -EEXIST;
|
||||
}
|
||||
*ptr = bs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void release_drive(Object *obj, const char *name, void *opaque)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
bdrv_detach_dev(*ptr, dev);
|
||||
blockdev_auto_del(*ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *print_drive(void *ptr)
|
||||
{
|
||||
return bdrv_get_device_name(ptr);
|
||||
}
|
||||
|
||||
static void get_drive(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
get_pointer(obj, v, opaque, print_drive, name, errp);
|
||||
}
|
||||
|
||||
static void set_drive(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
set_pointer(obj, v, opaque, parse_drive, name, errp);
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_drive = {
|
||||
.name = "drive",
|
||||
.get = get_drive,
|
||||
.set = set_drive,
|
||||
.release = release_drive,
|
||||
};
|
||||
|
||||
/* --- character device --- */
|
||||
|
||||
static int parse_chr(DeviceState *dev, const char *str, void **ptr)
|
||||
{
|
||||
CharDriverState *chr = qemu_chr_find(str);
|
||||
if (chr == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
if (chr->avail_connections < 1) {
|
||||
return -EEXIST;
|
||||
}
|
||||
*ptr = chr;
|
||||
--chr->avail_connections;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void release_chr(Object *obj, const char *name, void *opaque)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *print_chr(void *ptr)
|
||||
{
|
||||
CharDriverState *chr = ptr;
|
||||
|
||||
return chr->label ? chr->label : "";
|
||||
}
|
||||
|
||||
static void get_chr(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
get_pointer(obj, v, opaque, print_chr, name, errp);
|
||||
}
|
||||
|
||||
static void set_chr(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
set_pointer(obj, v, opaque, parse_chr, name, errp);
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_chr = {
|
||||
.name = "chr",
|
||||
.get = get_chr,
|
||||
.set = set_chr,
|
||||
.release = release_chr,
|
||||
};
|
||||
|
||||
/* --- netdev device --- */
|
||||
|
||||
static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
|
||||
{
|
||||
NetClientState *netdev = qemu_find_netdev(str);
|
||||
|
||||
if (netdev == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
if (netdev->peer) {
|
||||
return -EEXIST;
|
||||
}
|
||||
*ptr = netdev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *print_netdev(void *ptr)
|
||||
{
|
||||
NetClientState *netdev = ptr;
|
||||
|
||||
return netdev->name ? netdev->name : "";
|
||||
}
|
||||
|
||||
static void get_netdev(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
get_pointer(obj, v, opaque, print_netdev, name, errp);
|
||||
}
|
||||
|
||||
static void set_netdev(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
set_pointer(obj, v, opaque, parse_netdev, name, errp);
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_netdev = {
|
||||
.name = "netdev",
|
||||
.get = get_netdev,
|
||||
.set = set_netdev,
|
||||
};
|
||||
|
||||
/* --- vlan --- */
|
||||
|
||||
static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
|
||||
{
|
||||
NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
int id;
|
||||
if (!net_hub_id_for_client(*ptr, &id)) {
|
||||
return snprintf(dest, len, "%d", id);
|
||||
}
|
||||
}
|
||||
|
||||
return snprintf(dest, len, "<null>");
|
||||
}
|
||||
|
||||
static void get_vlan(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
int32_t id = -1;
|
||||
|
||||
if (*ptr) {
|
||||
int hub_id;
|
||||
if (!net_hub_id_for_client(*ptr, &hub_id)) {
|
||||
id = hub_id;
|
||||
}
|
||||
}
|
||||
|
||||
visit_type_int32(v, &id, name, errp);
|
||||
}
|
||||
|
||||
static void set_vlan(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
Error *local_err = NULL;
|
||||
int32_t id;
|
||||
NetClientState *hubport;
|
||||
|
||||
if (dev->state != DEV_STATE_CREATED) {
|
||||
error_set(errp, QERR_PERMISSION_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
visit_type_int32(v, &id, name, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
if (id == -1) {
|
||||
*ptr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
hubport = net_hub_port_find(id);
|
||||
if (!hubport) {
|
||||
error_set(errp, QERR_INVALID_PARAMETER_VALUE,
|
||||
name, prop->info->name);
|
||||
return;
|
||||
}
|
||||
*ptr = hubport;
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_vlan = {
|
||||
.name = "vlan",
|
||||
.print = print_vlan,
|
||||
.get = get_vlan,
|
||||
.set = set_vlan,
|
||||
};
|
||||
|
||||
int qdev_prop_set_drive(DeviceState *dev, const char *name,
|
||||
BlockDriverState *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
|
||||
object_property_set_str(OBJECT(dev), bdrv_name,
|
||||
name, &errp);
|
||||
if (errp) {
|
||||
qerror_report_err(errp);
|
||||
error_free(errp);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name,
|
||||
BlockDriverState *value)
|
||||
{
|
||||
if (qdev_prop_set_drive(dev, name, value) < 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
void qdev_prop_set_chr(DeviceState *dev, const char *name,
|
||||
CharDriverState *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
assert(!value || value->label);
|
||||
object_property_set_str(OBJECT(dev),
|
||||
value ? value->label : "", name, &errp);
|
||||
assert_no_error(errp);
|
||||
}
|
||||
|
||||
void qdev_prop_set_netdev(DeviceState *dev, const char *name,
|
||||
NetClientState *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
assert(!value || value->name);
|
||||
object_property_set_str(OBJECT(dev),
|
||||
value ? value->name : "", name, &errp);
|
||||
assert_no_error(errp);
|
||||
}
|
||||
|
||||
void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
|
||||
{
|
||||
qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
|
||||
if (nd->netdev) {
|
||||
qdev_prop_set_netdev(dev, "netdev", nd->netdev);
|
||||
}
|
||||
if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
|
||||
object_property_find(OBJECT(dev), "vectors", NULL)) {
|
||||
qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
|
||||
}
|
||||
nd->instantiated = 1;
|
||||
}
|
||||
|
||||
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
|
||||
{
|
||||
GlobalProperty *g;
|
||||
|
||||
g = g_malloc0(sizeof(*g));
|
||||
g->driver = qemu_opt_get(opts, "driver");
|
||||
g->property = qemu_opt_get(opts, "property");
|
||||
g->value = qemu_opt_get(opts, "value");
|
||||
qdev_prop_register_global(g);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qemu_add_globals(void)
|
||||
{
|
||||
qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
|
||||
}
|
|
@ -14,49 +14,6 @@ void *qdev_get_prop_ptr(DeviceState *dev, Property *prop)
|
|||
return ptr;
|
||||
}
|
||||
|
||||
static void get_pointer(Object *obj, Visitor *v, Property *prop,
|
||||
const char *(*print)(void *ptr),
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
void **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
char *p;
|
||||
|
||||
p = (char *) (*ptr ? print(*ptr) : "");
|
||||
visit_type_str(v, &p, name, errp);
|
||||
}
|
||||
|
||||
static void set_pointer(Object *obj, Visitor *v, Property *prop,
|
||||
int (*parse)(DeviceState *dev, const char *str,
|
||||
void **ptr),
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Error *local_err = NULL;
|
||||
void **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
char *str;
|
||||
int ret;
|
||||
|
||||
if (dev->state != DEV_STATE_CREATED) {
|
||||
error_set(errp, QERR_PERMISSION_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
visit_type_str(v, &str, name, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
if (!*str) {
|
||||
g_free(str);
|
||||
*ptr = NULL;
|
||||
return;
|
||||
}
|
||||
ret = parse(dev, str, ptr);
|
||||
error_set_from_qdev_prop_error(errp, ret, dev, prop, str);
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
static void get_enum(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
|
@ -96,10 +53,11 @@ static void bit_prop_set(DeviceState *dev, Property *props, bool val)
|
|||
{
|
||||
uint32_t *p = qdev_get_prop_ptr(dev, props);
|
||||
uint32_t mask = qdev_get_prop_mask(props);
|
||||
if (val)
|
||||
if (val) {
|
||||
*p |= mask;
|
||||
else
|
||||
} else {
|
||||
*p &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
|
||||
|
@ -421,11 +379,13 @@ static void release_string(Object *obj, const char *name, void *opaque)
|
|||
g_free(*(char **)qdev_get_prop_ptr(DEVICE(obj), prop));
|
||||
}
|
||||
|
||||
static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
|
||||
static int print_string(DeviceState *dev, Property *prop, char *dest,
|
||||
size_t len)
|
||||
{
|
||||
char **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
if (!*ptr)
|
||||
if (!*ptr) {
|
||||
return snprintf(dest, len, "<null>");
|
||||
}
|
||||
return snprintf(dest, len, "\"%s\"", *ptr);
|
||||
}
|
||||
|
||||
|
@ -477,227 +437,6 @@ PropertyInfo qdev_prop_string = {
|
|||
.set = set_string,
|
||||
};
|
||||
|
||||
/* --- drive --- */
|
||||
|
||||
static int parse_drive(DeviceState *dev, const char *str, void **ptr)
|
||||
{
|
||||
BlockDriverState *bs;
|
||||
|
||||
bs = bdrv_find(str);
|
||||
if (bs == NULL)
|
||||
return -ENOENT;
|
||||
if (bdrv_attach_dev(bs, dev) < 0)
|
||||
return -EEXIST;
|
||||
*ptr = bs;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void release_drive(Object *obj, const char *name, void *opaque)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
BlockDriverState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
bdrv_detach_dev(*ptr, dev);
|
||||
blockdev_auto_del(*ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *print_drive(void *ptr)
|
||||
{
|
||||
return bdrv_get_device_name(ptr);
|
||||
}
|
||||
|
||||
static void get_drive(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
get_pointer(obj, v, opaque, print_drive, name, errp);
|
||||
}
|
||||
|
||||
static void set_drive(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
set_pointer(obj, v, opaque, parse_drive, name, errp);
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_drive = {
|
||||
.name = "drive",
|
||||
.get = get_drive,
|
||||
.set = set_drive,
|
||||
.release = release_drive,
|
||||
};
|
||||
|
||||
/* --- character device --- */
|
||||
|
||||
static int parse_chr(DeviceState *dev, const char *str, void **ptr)
|
||||
{
|
||||
CharDriverState *chr = qemu_chr_find(str);
|
||||
if (chr == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
if (chr->avail_connections < 1) {
|
||||
return -EEXIST;
|
||||
}
|
||||
*ptr = chr;
|
||||
--chr->avail_connections;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void release_chr(Object *obj, const char *name, void *opaque)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
qemu_chr_add_handlers(*ptr, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const char *print_chr(void *ptr)
|
||||
{
|
||||
CharDriverState *chr = ptr;
|
||||
|
||||
return chr->label ? chr->label : "";
|
||||
}
|
||||
|
||||
static void get_chr(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
get_pointer(obj, v, opaque, print_chr, name, errp);
|
||||
}
|
||||
|
||||
static void set_chr(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
set_pointer(obj, v, opaque, parse_chr, name, errp);
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_chr = {
|
||||
.name = "chr",
|
||||
.get = get_chr,
|
||||
.set = set_chr,
|
||||
.release = release_chr,
|
||||
};
|
||||
|
||||
/* --- netdev device --- */
|
||||
|
||||
static int parse_netdev(DeviceState *dev, const char *str, void **ptr)
|
||||
{
|
||||
NetClientState *netdev = qemu_find_netdev(str);
|
||||
|
||||
if (netdev == NULL) {
|
||||
return -ENOENT;
|
||||
}
|
||||
if (netdev->peer) {
|
||||
return -EEXIST;
|
||||
}
|
||||
*ptr = netdev;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *print_netdev(void *ptr)
|
||||
{
|
||||
NetClientState *netdev = ptr;
|
||||
|
||||
return netdev->name ? netdev->name : "";
|
||||
}
|
||||
|
||||
static void get_netdev(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
get_pointer(obj, v, opaque, print_netdev, name, errp);
|
||||
}
|
||||
|
||||
static void set_netdev(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
set_pointer(obj, v, opaque, parse_netdev, name, errp);
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_netdev = {
|
||||
.name = "netdev",
|
||||
.get = get_netdev,
|
||||
.set = set_netdev,
|
||||
};
|
||||
|
||||
/* --- vlan --- */
|
||||
|
||||
static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
|
||||
{
|
||||
NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
if (*ptr) {
|
||||
int id;
|
||||
if (!net_hub_id_for_client(*ptr, &id)) {
|
||||
return snprintf(dest, len, "%d", id);
|
||||
}
|
||||
}
|
||||
|
||||
return snprintf(dest, len, "<null>");
|
||||
}
|
||||
|
||||
static void get_vlan(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
int32_t id = -1;
|
||||
|
||||
if (*ptr) {
|
||||
int hub_id;
|
||||
if (!net_hub_id_for_client(*ptr, &hub_id)) {
|
||||
id = hub_id;
|
||||
}
|
||||
}
|
||||
|
||||
visit_type_int32(v, &id, name, errp);
|
||||
}
|
||||
|
||||
static void set_vlan(Object *obj, Visitor *v, void *opaque,
|
||||
const char *name, Error **errp)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
Property *prop = opaque;
|
||||
NetClientState **ptr = qdev_get_prop_ptr(dev, prop);
|
||||
Error *local_err = NULL;
|
||||
int32_t id;
|
||||
NetClientState *hubport;
|
||||
|
||||
if (dev->state != DEV_STATE_CREATED) {
|
||||
error_set(errp, QERR_PERMISSION_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
visit_type_int32(v, &id, name, &local_err);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
if (id == -1) {
|
||||
*ptr = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
hubport = net_hub_port_find(id);
|
||||
if (!hubport) {
|
||||
error_set(errp, QERR_INVALID_PARAMETER_VALUE,
|
||||
name, prop->info->name);
|
||||
return;
|
||||
}
|
||||
*ptr = hubport;
|
||||
}
|
||||
|
||||
PropertyInfo qdev_prop_vlan = {
|
||||
.name = "vlan",
|
||||
.print = print_vlan,
|
||||
.get = get_vlan,
|
||||
.set = set_vlan,
|
||||
};
|
||||
|
||||
/* --- pointer --- */
|
||||
|
||||
/* Not a proper property, just for dirty hacks. TODO Remove it! */
|
||||
|
@ -750,16 +489,20 @@ static void set_mac(Object *obj, Visitor *v, void *opaque,
|
|||
}
|
||||
|
||||
for (i = 0, pos = 0; i < 6; i++, pos += 3) {
|
||||
if (!qemu_isxdigit(str[pos]))
|
||||
if (!qemu_isxdigit(str[pos])) {
|
||||
goto inval;
|
||||
if (!qemu_isxdigit(str[pos+1]))
|
||||
}
|
||||
if (!qemu_isxdigit(str[pos+1])) {
|
||||
goto inval;
|
||||
}
|
||||
if (i == 5) {
|
||||
if (str[pos+2] != '\0')
|
||||
if (str[pos+2] != '\0') {
|
||||
goto inval;
|
||||
}
|
||||
} else {
|
||||
if (str[pos+2] != ':' && str[pos+2] != '-')
|
||||
if (str[pos+2] != ':' && str[pos+2] != '-') {
|
||||
goto inval;
|
||||
}
|
||||
}
|
||||
mac->a[i] = strtol(str+pos, &p, 16);
|
||||
}
|
||||
|
@ -865,7 +608,8 @@ invalid:
|
|||
g_free(str);
|
||||
}
|
||||
|
||||
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
|
||||
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
|
||||
size_t len)
|
||||
{
|
||||
int32_t *ptr = qdev_get_prop_ptr(dev, prop);
|
||||
|
||||
|
@ -1039,11 +783,13 @@ PropertyInfo qdev_prop_pci_host_devaddr = {
|
|||
|
||||
static Property *qdev_prop_walk(Property *props, const char *name)
|
||||
{
|
||||
if (!props)
|
||||
if (!props) {
|
||||
return NULL;
|
||||
}
|
||||
while (props->name) {
|
||||
if (strcmp(props->name, name) == 0)
|
||||
if (strcmp(props->name, name) == 0) {
|
||||
return props;
|
||||
}
|
||||
props++;
|
||||
}
|
||||
return NULL;
|
||||
|
@ -1159,44 +905,6 @@ void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value)
|
|||
assert_no_error(errp);
|
||||
}
|
||||
|
||||
int qdev_prop_set_drive(DeviceState *dev, const char *name, BlockDriverState *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
const char *bdrv_name = value ? bdrv_get_device_name(value) : "";
|
||||
object_property_set_str(OBJECT(dev), bdrv_name,
|
||||
name, &errp);
|
||||
if (errp) {
|
||||
qerror_report_err(errp);
|
||||
error_free(errp);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qdev_prop_set_drive_nofail(DeviceState *dev, const char *name, BlockDriverState *value)
|
||||
{
|
||||
if (qdev_prop_set_drive(dev, name, value) < 0) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
assert(!value || value->label);
|
||||
object_property_set_str(OBJECT(dev),
|
||||
value ? value->label : "", name, &errp);
|
||||
assert_no_error(errp);
|
||||
}
|
||||
|
||||
void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
assert(!value || value->name);
|
||||
object_property_set_str(OBJECT(dev),
|
||||
value ? value->name : "", name, &errp);
|
||||
assert_no_error(errp);
|
||||
}
|
||||
|
||||
void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value)
|
||||
{
|
||||
Error *errp = NULL;
|
||||
|
@ -1230,9 +938,10 @@ void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value)
|
|||
*ptr = value;
|
||||
}
|
||||
|
||||
static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
|
||||
static QTAILQ_HEAD(, GlobalProperty) global_props =
|
||||
QTAILQ_HEAD_INITIALIZER(global_props);
|
||||
|
||||
static void qdev_prop_register_global(GlobalProperty *prop)
|
||||
void qdev_prop_register_global(GlobalProperty *prop)
|
||||
{
|
||||
QTAILQ_INSERT_TAIL(&global_props, prop, next);
|
||||
}
|
||||
|
@ -1263,20 +972,3 @@ void qdev_prop_set_globals(DeviceState *dev)
|
|||
class = object_class_get_parent(class);
|
||||
} while (class);
|
||||
}
|
||||
|
||||
static int qdev_add_one_global(QemuOpts *opts, void *opaque)
|
||||
{
|
||||
GlobalProperty *g;
|
||||
|
||||
g = g_malloc0(sizeof(*g));
|
||||
g->driver = qemu_opt_get(opts, "driver");
|
||||
g->property = qemu_opt_get(opts, "property");
|
||||
g->value = qemu_opt_get(opts, "value");
|
||||
qdev_prop_register_global(g);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qemu_add_globals(void)
|
||||
{
|
||||
qemu_opts_foreach(qemu_find_opts("global"), qdev_add_one_global, NULL, 0);
|
||||
}
|
||||
|
|
|
@ -116,6 +116,7 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value);
|
|||
/* FIXME: Remove opaque pointer properties. */
|
||||
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
|
||||
|
||||
void qdev_prop_register_global(GlobalProperty *prop);
|
||||
void qdev_prop_register_global_list(GlobalProperty *props);
|
||||
void qdev_prop_set_globals(DeviceState *dev);
|
||||
void error_set_from_qdev_prop_error(Error **errp, int ret, DeviceState *dev,
|
||||
|
|
13
hw/qdev.c
13
hw/qdev.c
|
@ -25,7 +25,6 @@
|
|||
inherit from a particular bus (e.g. PCI or I2C) rather than
|
||||
this API directly. */
|
||||
|
||||
#include "net/net.h"
|
||||
#include "qdev.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qapi/error.h"
|
||||
|
@ -312,18 +311,6 @@ void qdev_connect_gpio_out(DeviceState * dev, int n, qemu_irq pin)
|
|||
dev->gpio_out[n] = pin;
|
||||
}
|
||||
|
||||
void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
|
||||
{
|
||||
qdev_prop_set_macaddr(dev, "mac", nd->macaddr.a);
|
||||
if (nd->netdev)
|
||||
qdev_prop_set_netdev(dev, "netdev", nd->netdev);
|
||||
if (nd->nvectors != DEV_NVECTORS_UNSPECIFIED &&
|
||||
object_property_find(OBJECT(dev), "vectors", NULL)) {
|
||||
qdev_prop_set_uint32(dev, "vectors", nd->nvectors);
|
||||
}
|
||||
nd->instantiated = 1;
|
||||
}
|
||||
|
||||
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
|
||||
{
|
||||
BusState *bus;
|
||||
|
|
|
@ -110,10 +110,12 @@ VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
|
|||
return bus;
|
||||
}
|
||||
|
||||
static void s390_virtio_irq(CPUS390XState *env, int config_change, uint64_t token)
|
||||
static void s390_virtio_irq(S390CPU *cpu, int config_change, uint64_t token)
|
||||
{
|
||||
CPUS390XState *env = &cpu->env;
|
||||
|
||||
if (kvm_enabled()) {
|
||||
kvm_s390_virtio_irq(env, config_change, token);
|
||||
kvm_s390_virtio_irq(cpu, config_change, token);
|
||||
} else {
|
||||
cpu_inject_ext(env, VIRTIO_EXT_CODE, config_change, token);
|
||||
}
|
||||
|
@ -142,8 +144,7 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
|
|||
s390_virtio_reset_idx(dev);
|
||||
if (dev->qdev.hotplugged) {
|
||||
S390CPU *cpu = s390_cpu_addr2state(0);
|
||||
CPUS390XState *env = &cpu->env;
|
||||
s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
|
||||
s390_virtio_irq(cpu, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -368,9 +369,8 @@ static void virtio_s390_notify(void *opaque, uint16_t vector)
|
|||
VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
|
||||
uint64_t token = s390_virtio_device_vq_token(dev, vector);
|
||||
S390CPU *cpu = s390_cpu_addr2state(0);
|
||||
CPUS390XState *env = &cpu->env;
|
||||
|
||||
s390_virtio_irq(env, 0, token);
|
||||
s390_virtio_irq(cpu, 0, token);
|
||||
}
|
||||
|
||||
static unsigned virtio_s390_get_features(void *opaque)
|
||||
|
|
|
@ -798,7 +798,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
|
|||
|
||||
/* Tell KVM that we're in PAPR mode */
|
||||
if (kvm_enabled()) {
|
||||
kvmppc_set_papr(env);
|
||||
kvmppc_set_papr(cpu);
|
||||
}
|
||||
|
||||
qemu_register_reset(spapr_cpu_reset, cpu);
|
||||
|
|
|
@ -93,7 +93,7 @@ static PowerPCCPU *ppc440_init_xilinx(ram_addr_t *ram_size,
|
|||
}
|
||||
env = &cpu->env;
|
||||
|
||||
ppc_booke_timers_init(env, sysclk, 0/* no flags */);
|
||||
ppc_booke_timers_init(cpu, sysclk, 0/* no flags */);
|
||||
|
||||
ppc_dcr_init(env, NULL, NULL);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue