mirror of https://github.com/proxmox/mirror_qemu
Add PAPR H_VIO_SIGNAL hypercall and infrastructure for VIO interrupts
This patch adds infrastructure to support interrupts from PAPR virtual IO devices. This includes correctly advertising those interrupts in the device tree, and implementing the H_VIO_SIGNAL hypercall, used to enable and disable individual device interrupts. Signed-off-by: David Gibson <dwg@au1.ibm.com> Signed-off-by: Alexander Graf <agraf@suse.de>master
parent
b5cec4c5f2
commit
00dc738d8a
|
@ -65,7 +65,7 @@ static void *spapr_create_fdt(int *fdt_size, ram_addr_t ramsize,
|
|||
uint32_t start_prop = cpu_to_be32(initrd_base);
|
||||
uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size);
|
||||
uint32_t pft_size_prop[] = {0, cpu_to_be32(hash_shift)};
|
||||
char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr";
|
||||
char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt";
|
||||
uint32_t interrupt_server_ranges_prop[] = {0, cpu_to_be32(smp_cpus)};
|
||||
int i;
|
||||
char *modelname;
|
||||
|
|
|
@ -105,6 +105,16 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
|
|||
}
|
||||
}
|
||||
|
||||
if (dev->qirq) {
|
||||
uint32_t ints_prop[] = {cpu_to_be32(dev->vio_irq_num), 0};
|
||||
|
||||
ret = fdt_setprop(fdt, node_off, "interrupts", ints_prop,
|
||||
sizeof(ints_prop));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->devnode) {
|
||||
ret = (info->devnode)(dev, fdt, node_off);
|
||||
if (ret < 0) {
|
||||
|
@ -140,6 +150,30 @@ void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info)
|
|||
qdev_register(&info->qdev);
|
||||
}
|
||||
|
||||
static target_ulong h_vio_signal(CPUState *env, sPAPREnvironment *spapr,
|
||||
target_ulong opcode,
|
||||
target_ulong *args)
|
||||
{
|
||||
target_ulong reg = args[0];
|
||||
target_ulong mode = args[1];
|
||||
VIOsPAPRDevice *dev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
|
||||
VIOsPAPRDeviceInfo *info;
|
||||
|
||||
if (!dev) {
|
||||
return H_PARAMETER;
|
||||
}
|
||||
|
||||
info = (VIOsPAPRDeviceInfo *)dev->qdev.info;
|
||||
|
||||
if (mode & ~info->signal_mask) {
|
||||
return H_PARAMETER;
|
||||
}
|
||||
|
||||
dev->signal_state = mode;
|
||||
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
VIOsPAPRBus *spapr_vio_bus_init(void)
|
||||
{
|
||||
VIOsPAPRBus *bus;
|
||||
|
@ -156,6 +190,9 @@ VIOsPAPRBus *spapr_vio_bus_init(void)
|
|||
qbus = qbus_create(&spapr_vio_bus_info, dev, "spapr-vio");
|
||||
bus = DO_UPCAST(VIOsPAPRBus, bus, qbus);
|
||||
|
||||
/* hcall-vio */
|
||||
spapr_register_hypercall(H_VIO_SIGNAL, h_vio_signal);
|
||||
|
||||
for (qinfo = device_info_list; qinfo; qinfo = qinfo->next) {
|
||||
VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)qinfo;
|
||||
|
||||
|
|
|
@ -24,6 +24,9 @@
|
|||
typedef struct VIOsPAPRDevice {
|
||||
DeviceState qdev;
|
||||
uint32_t reg;
|
||||
qemu_irq qirq;
|
||||
uint32_t vio_irq_num;
|
||||
target_ulong signal_state;
|
||||
} VIOsPAPRDevice;
|
||||
|
||||
typedef struct VIOsPAPRBus {
|
||||
|
@ -33,6 +36,7 @@ typedef struct VIOsPAPRBus {
|
|||
typedef struct {
|
||||
DeviceInfo qdev;
|
||||
const char *dt_name, *dt_type, *dt_compatible;
|
||||
target_ulong signal_mask;
|
||||
int (*init)(VIOsPAPRDevice *dev);
|
||||
void (*hcalls)(VIOsPAPRBus *bus);
|
||||
int (*devnode)(VIOsPAPRDevice *dev, void *fdt, int node_off);
|
||||
|
@ -43,6 +47,8 @@ extern VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg);
|
|||
extern void spapr_vio_bus_register_withprop(VIOsPAPRDeviceInfo *info);
|
||||
extern int spapr_populate_vdevice(VIOsPAPRBus *bus, void *fdt);
|
||||
|
||||
extern int spapr_vio_signal(VIOsPAPRDevice *dev, target_ulong mode);
|
||||
|
||||
void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
|
||||
void spapr_vty_create(VIOsPAPRBus *bus,
|
||||
uint32_t reg, CharDriverState *chardev);
|
||||
|
|
Loading…
Reference in New Issue