e2k: very basic SIC emulation

This commit is contained in:
Alibek Omarov 2021-07-14 16:46:34 +03:00
parent 8de04976c0
commit dbc7cacc8d
2 changed files with 273 additions and 51 deletions

View File

@ -1,6 +1,8 @@
/*
* Copyright (c) 2021 Alibek Omarov
*
* System Interchange Controller emulation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2 or later, as published by the Free Software Foundation.
@ -12,7 +14,7 @@
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#include "qemu/osdep.h"
#include "qemu/datadir.h"
#include "qemu/log.h"
@ -30,79 +32,258 @@
#define ES2_NSR_AREA_PHYS_BASE 0x0000000110000000UL /* node 0 */
#define ES2_NBSR_AREA_SIZE 0x0000000000100000UL
enum SICRegsAddrs
{
SIC_node_offset = 0x4,
SIC_st_p = 0x0,
SIC_rt_lcfg0 = 0x10, /* node configuration, max nodes 4 */
SIC_rt_mhi0 = 0x20,
SIC_rt_mlo0 = 0x30,
SIC_rt_pcim0 = 0x40,
SIC_rt_pciio0 = 0x50,
SIC_rt_ioapic0 = 0x60,
SIC_rt_pcicfgb = 0x90,
SIC_st_core = 0x100, /* core configuration, max cores 16 */
/* IO link & RDMA */
SIC_iol_csr = 0x900,
SIC_unknown_0x1040 = 0x1040,
SIC_unknown_0x1050 = 0x1050,
SIC_rt_ioapic10 = 0x1060,
/* Second IO link */
SIC_iol_csr1 = 0x1900,
};
#define SIC_rt_msi 0xb0
#define SIC_rt_msi_h 0xb4
#define SIC_rt_pcim0 0x40
#define SIC_rt_pcim1 0x44
#define SIC_rt_pcim2 0x48
#define SIC_rt_pcim3 0x4c
#define SIC_rt_pciio0 0x50
#define SIC_rt_pciio1 0x54
#define SIC_rt_pciio2 0x58
#define SIC_rt_pciio3 0x5c
#define SIC_rt_pcimp_b0 0x70
#define SIC_rt_pcimp_b1 0x74
#define SIC_rt_pcimp_b2 0x78
#define SIC_rt_pcimp_b3 0x7c
#define SIC_rt_pcimp_e0 0x80
#define SIC_rt_pcimp_e1 0x84
#define SIC_rt_pcimp_e2 0x88
#define SIC_rt_pcimp_e3 0x8c
#define SIC_rt_pcicfgb 0x90
#define SIC_prepic_ctrl2 0x8030
#define SIC_prepic_err_stat 0x8040
#define SIC_prepic_err_int 0x8060
#define SIC_prepic_linp0 0x8c00
#define SIC_prepic_linp1 0x8c04
#define SIC_prepic_linp2 0x8c08
#define SIC_prepic_linp3 0x8c0c
#define SIC_prepic_linp4 0x8c10
#define SIC_prepic_linp5 0x8c14
#define SIC_iommu_ctrl 0x0380
#define SIC_iommu_ba_lo 0x0390
#define SIC_iommu_dtba_lo 0x0398
#define SIC_iommu_err 0x03b0
#define SIC_iommu_err_info_lo 0x03b8
static uint64_t sic_mem_read(void *opaque, hwaddr addr, unsigned size)
{
// E2KMachineState *ms = opaque;
uint64_t val;
E2KMachineState *ms = opaque;
SICState *regs = &ms->sicregs;
uint64_t ret;
int index;
if (size < 4) {
return 0;
}
index = addr & (ES2_NBSR_AREA_SIZE - 1);
switch (index) {
case SIC_rt_msi:
ret = regs->rt_msi & 0xffffffff;
break;
case SIC_rt_msi_h:
ret = regs->rt_msi >> 32;
break;
case SIC_rt_pcim0:
val = 0;
ret = regs->rt_pcim0;
break;
case SIC_rt_pcim1:
ret = regs->rt_pcim1;
break;
case SIC_rt_pcim2:
ret = regs->rt_pcim2;
break;
case SIC_rt_pcim3:
ret = regs->rt_pcim3;
break;
case SIC_rt_pciio0:
val = 0;
ret = regs->rt_pciio0;
break;
case SIC_rt_pciio1:
ret = regs->rt_pciio1;
break;
case SIC_rt_pciio2:
ret = regs->rt_pciio2;
break;
case SIC_rt_pciio3:
ret = regs->rt_pciio3;
break;
case SIC_rt_pcimp_b0:
ret = regs->rt_pcimp_b0;
break;
case SIC_rt_pcimp_b1:
ret = regs->rt_pcimp_b1;
break;
case SIC_rt_pcimp_b2:
ret = regs->rt_pcimp_b2;
break;
case SIC_rt_pcimp_b3:
ret = regs->rt_pcimp_b3;
break;
case SIC_rt_pcimp_e0:
ret = regs->rt_pcimp_e0;
break;
case SIC_rt_pcimp_e1:
ret = regs->rt_pcimp_e1;
break;
case SIC_rt_pcimp_e2:
ret = regs->rt_pcimp_e2;
break;
case SIC_rt_pcimp_e3:
ret = regs->rt_pcimp_e3;
break;
case SIC_rt_pcicfgb:
// TODO: io page address [48:12]
// TODO: page + 0x8044 = 16-bit reg
val = 0xdeadbeef000 >> 12;
ret = regs->rt_pcicfgb;
break;
case SIC_prepic_ctrl2:
ret = regs->prepic_ctrl2;
break;
case SIC_prepic_err_stat:
ret = regs->prepic_err_stat;
break;
case SIC_prepic_err_int:
ret = regs->prepic_err_int;
break;
case SIC_prepic_linp0:
ret = regs->prepic_linp0;
break;
case SIC_prepic_linp1:
ret = regs->prepic_linp1;
break;
case SIC_prepic_linp2:
ret = regs->prepic_linp2;
break;
case SIC_prepic_linp3:
ret = regs->prepic_linp3;
break;
case SIC_prepic_linp4:
ret = regs->prepic_linp4;
break;
case SIC_prepic_linp5:
ret = regs->prepic_linp5;
break;
case SIC_iommu_err:
ret = regs->iommu_err;
break;
case SIC_iommu_err_info_lo:
ret = regs->iommu_err_info;
break;
default:
val = 0;
qemu_log_mask(LOG_UNIMP, "%s: unknown SIC register 0x%x\n", __FUNCTION__, index);
ret = 0;
break;
}
trace_sic_mem_readl(addr, val);
return val;
trace_sic_mem_readl(addr, ret);
return ret;
}
static void sic_mem_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
// E2KMachineState *ms = opaque;
E2KMachineState *ms = opaque;
SICState *regs = &ms->sicregs;
int index;
trace_sic_mem_writel(addr, val);
index = addr & (ES2_NBSR_AREA_SIZE - 1);
switch (index) {
case SIC_rt_msi:
regs->rt_msi = (regs->rt_msi & 0xffffffff00000000) | val;
break;
case SIC_rt_msi_h:
regs->rt_msi = (regs->rt_msi & 0x00000000ffffffff) | (val << 32);
break;
case SIC_rt_pcim0:
regs->rt_pcim0 = val;
break;
case SIC_rt_pcim1:
regs->rt_pcim1 = val;
break;
case SIC_rt_pcim2:
regs->rt_pcim2 = val;
break;
case SIC_rt_pcim3:
regs->rt_pcim3 = val;
break;
case SIC_rt_pciio0:
regs->rt_pciio0 = val;
break;
case SIC_rt_pciio1:
regs->rt_pciio1 = val;
break;
case SIC_rt_pciio2:
regs->rt_pciio2 = val;
break;
case SIC_rt_pciio3:
regs->rt_pciio3 = val;
break;
case SIC_rt_pcimp_b0:
regs->rt_pcimp_b0 = val;
break;
case SIC_rt_pcimp_b1:
regs->rt_pcimp_b1 = val;
break;
case SIC_rt_pcimp_b2:
regs->rt_pcimp_b2 = val;
break;
case SIC_rt_pcimp_b3:
regs->rt_pcimp_b3 = val;
break;
case SIC_rt_pcimp_e0:
regs->rt_pcimp_e0 = val;
break;
case SIC_rt_pcimp_e1:
regs->rt_pcimp_e1 = val;
break;
case SIC_rt_pcimp_e2:
regs->rt_pcimp_e2 = val;
break;
case SIC_rt_pcimp_e3:
regs->rt_pcimp_e3 = val;
break;
case SIC_rt_pcicfgb:
regs->rt_pcicfgb = val;
break;
case SIC_prepic_ctrl2:
regs->prepic_ctrl2 = val;
break;
case SIC_prepic_err_stat:
regs->prepic_err_stat = val;
break;
case SIC_prepic_err_int:
regs->prepic_err_int = val;
break;
case SIC_prepic_linp0:
regs->prepic_linp0 = val;
break;
case SIC_prepic_linp1:
regs->prepic_linp1 = val;
break;
case SIC_prepic_linp2:
regs->prepic_linp2 = val;
break;
case SIC_prepic_linp3:
regs->prepic_linp3 = val;
break;
case SIC_prepic_linp4:
regs->prepic_linp4 = val;
break;
case SIC_prepic_linp5:
regs->prepic_linp5 = val;
break;
case SIC_iommu_ctrl:
regs->iommu_ctrl = val;
break;
case SIC_iommu_ba_lo:
regs->iommu_ptbar = val;
break;
case SIC_iommu_dtba_lo:
regs->iommu_dtbar = val;
break;
default:
qemu_log_mask(LOG_UNIMP, "%s: unknown SIC register 0x%x\n", __FUNCTION__, index);
break;
}
trace_sic_mem_writel(addr, val);
}
static const MemoryRegionOps sic_io_ops = {
@ -121,6 +302,8 @@ void sic_init(E2KMachineState *ms)
const hwaddr base = ES2_NSR_AREA_PHYS_BASE;
const uint64_t size = ES2_NBSR_AREA_SIZE;
memset(&ms->sicregs, 0, sizeof(ms->sicregs));
io_memory = g_malloc(sizeof(*io_memory));
memory_region_init_io(io_memory, OBJECT(ms), &sic_io_ops, ms, "sic-msi",
size);

View File

@ -23,6 +23,41 @@
#include "qom/object.h"
#include "hw/e2k/ioapic.h"
typedef struct SICState {
uint32_t rt_pcim0;
uint32_t rt_pcim1;
uint32_t rt_pcim2;
uint32_t rt_pcim3;
uint32_t rt_pciio0;
uint32_t rt_pciio1;
uint32_t rt_pciio2;
uint32_t rt_pciio3;
uint32_t rt_pcimp_b0;
uint32_t rt_pcimp_b1;
uint32_t rt_pcimp_b2;
uint32_t rt_pcimp_b3;
uint32_t rt_pcimp_e0;
uint32_t rt_pcimp_e1;
uint32_t rt_pcimp_e2;
uint32_t rt_pcimp_e3;
uint32_t rt_pcicfgb;
uint64_t rt_msi;
uint32_t iommu_ctrl;
uint64_t iommu_ptbar;
uint64_t iommu_dtbar;
uint64_t iommu_err;
uint64_t iommu_err_info;
uint32_t prepic_ctrl2;
uint32_t prepic_err_stat;
uint32_t prepic_err_int;
uint32_t prepic_linp0;
uint32_t prepic_linp1;
uint32_t prepic_linp2;
uint32_t prepic_linp3;
uint32_t prepic_linp4;
uint32_t prepic_linp5;
} SICState;
struct E2KMachineClass {
/*< private >*/
MachineClass parent;
@ -36,6 +71,10 @@ struct E2KMachineState {
/*< public >*/
qemu_irq *pic;
struct SICState sicregs;
AddressSpace *ioapic_as;
};
#define TYPE_E2K_MACHINE MACHINE_TYPE_NAME("e2k")