mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
pull-loongarch-20250514
-----BEGIN PGP SIGNATURE----- iLMEAAEKAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCaCRNgwAKCRBAov/yOSY+ 343NBACeXLcXkNfPDRsuYC/Z0iYrMO8HuQ6VAcN1f4H+qP6Uo7ywb13GpJTLmewD iYmD93qVZBAglSUWhaVzBZbAjGFzZSDLcO0bmfsMvmUaIJfIZkJqRG01shk9iMMR zDLEax9udJdhJxBPCINNonXHds4vYKasjUureKd1SJidiBKG4w== =wdkQ -----END PGP SIGNATURE----- Merge tag 'pull-loongarch-20250514' of https://github.com/gaosong715/qemu into staging pull-loongarch-20250514 # -----BEGIN PGP SIGNATURE----- # # iLMEAAEKAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCaCRNgwAKCRBAov/yOSY+ # 343NBACeXLcXkNfPDRsuYC/Z0iYrMO8HuQ6VAcN1f4H+qP6Uo7ywb13GpJTLmewD # iYmD93qVZBAglSUWhaVzBZbAjGFzZSDLcO0bmfsMvmUaIJfIZkJqRG01shk9iMMR # zDLEax9udJdhJxBPCINNonXHds4vYKasjUureKd1SJidiBKG4w== # =wdkQ # -----END PGP SIGNATURE----- # gpg: Signature made Wed 14 May 2025 04:00:03 EDT # gpg: using RSA key B8FF1DA0D2FDCB2DA09C6C2C40A2FFF239263EDF # gpg: Good signature from "Song Gao <m17746591750@163.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: B8FF 1DA0 D2FD CB2D A09C 6C2C 40A2 FFF2 3926 3EDF * tag 'pull-loongarch-20250514' of https://github.com/gaosong715/qemu: hw/loongarch/boot: Adjust the loading position of the initrd hw/intc/loongarch_pch: Merge three memory region into one hw/intc/loongarch_pch: Set flexible memory access size with iomem region hw/intc/loongarch_pch: Rename memory region iomem32_low with iomem hw/intc/loongarch_pch: Use unified trace event for memory region ops hw/intc/loongarch_pch: Use generic write callback for iomem8 region hw/intc/loongarch_pch: Use generic write callback for iomem32_high region hw/intc/loongarch_pch: Use generic write callback for iomem32_low region hw/intc/loongarch_pch: Use generic read callback for iomem8 region hw/intc/loongarch_pch: Use generic read callback for iomem32_high region hw/intc/loongarch_pch: Use generic read callback for iomem32_low region hw/intc/loongarch_pch: Discard write operation with ISR register hw/intc/loongarch_pch: Use relative address in MemoryRegionOps hw/intc/loongarch_pch: Set version information at initial stage hw/intc/loongarch_pch: Remove some duplicate macro hw/intc/loongarch_pch: Modify register name PCH_PIC_xxx_OFFSET with PCH_PIC_xxx hw/intc/loongarch_pch: Modify name of some registers Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
8648138789
6 changed files with 196 additions and 273 deletions
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/intc/loongarch_pch_pic.h"
|
||||
#include "trace.h"
|
||||
|
@ -71,285 +72,181 @@ static void pch_pic_irq_handler(void *opaque, int irq, int level)
|
|||
pch_pic_update_irq(s, mask, level);
|
||||
}
|
||||
|
||||
static uint64_t loongarch_pch_pic_low_readw(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
static uint64_t pch_pic_read(void *opaque, hwaddr addr, uint64_t field_mask)
|
||||
{
|
||||
LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque);
|
||||
uint64_t val = 0;
|
||||
uint32_t offset = addr & 0xfff;
|
||||
uint32_t offset;
|
||||
|
||||
switch (offset) {
|
||||
case PCH_PIC_INT_ID_LO:
|
||||
val = PCH_PIC_INT_ID_VAL;
|
||||
offset = addr & 7;
|
||||
addr -= offset;
|
||||
switch (addr) {
|
||||
case PCH_PIC_INT_ID:
|
||||
val = s->id.data;
|
||||
break;
|
||||
case PCH_PIC_INT_ID_HI:
|
||||
/*
|
||||
* With 7A1000 manual
|
||||
* bit 0-15 pch irqchip version
|
||||
* bit 16-31 irq number supported with pch irqchip
|
||||
*/
|
||||
val = deposit32(PCH_PIC_INT_ID_VER, 16, 16, s->irq_num - 1);
|
||||
case PCH_PIC_INT_MASK:
|
||||
val = s->int_mask;
|
||||
break;
|
||||
case PCH_PIC_INT_MASK_LO:
|
||||
val = (uint32_t)s->int_mask;
|
||||
case PCH_PIC_INT_EDGE:
|
||||
val = s->intedge;
|
||||
break;
|
||||
case PCH_PIC_INT_MASK_HI:
|
||||
val = s->int_mask >> 32;
|
||||
case PCH_PIC_HTMSI_EN:
|
||||
val = s->htmsi_en;
|
||||
break;
|
||||
case PCH_PIC_INT_EDGE_LO:
|
||||
val = (uint32_t)s->intedge;
|
||||
case PCH_PIC_AUTO_CTRL0:
|
||||
case PCH_PIC_AUTO_CTRL1:
|
||||
/* PCH PIC connect to EXTIOI always, discard auto_ctrl access */
|
||||
break;
|
||||
case PCH_PIC_INT_EDGE_HI:
|
||||
val = s->intedge >> 32;
|
||||
case PCH_PIC_INT_STATUS:
|
||||
val = s->intisr & (~s->int_mask);
|
||||
break;
|
||||
case PCH_PIC_HTMSI_EN_LO:
|
||||
val = (uint32_t)s->htmsi_en;
|
||||
case PCH_PIC_INT_POL:
|
||||
val = s->int_polarity;
|
||||
break;
|
||||
case PCH_PIC_HTMSI_EN_HI:
|
||||
val = s->htmsi_en >> 32;
|
||||
case PCH_PIC_HTMSI_VEC ... PCH_PIC_HTMSI_VEC_END:
|
||||
val = *(uint64_t *)(s->htmsi_vector + addr - PCH_PIC_HTMSI_VEC);
|
||||
break;
|
||||
case PCH_PIC_AUTO_CTRL0_LO:
|
||||
case PCH_PIC_AUTO_CTRL0_HI:
|
||||
case PCH_PIC_AUTO_CTRL1_LO:
|
||||
case PCH_PIC_AUTO_CTRL1_HI:
|
||||
case PCH_PIC_ROUTE_ENTRY ... PCH_PIC_ROUTE_ENTRY_END:
|
||||
val = *(uint64_t *)(s->route_entry + addr - PCH_PIC_ROUTE_ENTRY);
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"pch_pic_read: Bad address 0x%"PRIx64"\n", addr);
|
||||
break;
|
||||
}
|
||||
|
||||
trace_loongarch_pch_pic_low_readw(size, addr, val);
|
||||
return val;
|
||||
return (val >> (offset * 8)) & field_mask;
|
||||
}
|
||||
|
||||
static uint64_t get_writew_val(uint64_t value, uint32_t target, bool hi)
|
||||
{
|
||||
uint64_t mask = 0xffffffff00000000;
|
||||
uint64_t data = target;
|
||||
|
||||
return hi ? (value & ~mask) | (data << 32) : (value & mask) | data;
|
||||
}
|
||||
|
||||
static void loongarch_pch_pic_low_writew(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned size)
|
||||
static void pch_pic_write(void *opaque, hwaddr addr, uint64_t value,
|
||||
uint64_t field_mask)
|
||||
{
|
||||
LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque);
|
||||
uint32_t offset, old_valid, data = (uint32_t)value;
|
||||
uint64_t old, int_mask;
|
||||
offset = addr & 0xfff;
|
||||
uint32_t offset;
|
||||
uint64_t old, mask, data, *ptemp;
|
||||
|
||||
trace_loongarch_pch_pic_low_writew(size, addr, data);
|
||||
offset = addr & 7;
|
||||
addr -= offset;
|
||||
mask = field_mask << (offset * 8);
|
||||
data = (value & field_mask) << (offset * 8);
|
||||
switch (addr) {
|
||||
case PCH_PIC_INT_MASK:
|
||||
old = s->int_mask;
|
||||
s->int_mask = (old & ~mask) | data;
|
||||
if (old & ~data) {
|
||||
pch_pic_update_irq(s, old & ~data, 1);
|
||||
}
|
||||
|
||||
switch (offset) {
|
||||
case PCH_PIC_INT_MASK_LO:
|
||||
old = s->int_mask;
|
||||
s->int_mask = get_writew_val(old, data, 0);
|
||||
old_valid = (uint32_t)old;
|
||||
if (old_valid & ~data) {
|
||||
pch_pic_update_irq(s, (old_valid & ~data), 1);
|
||||
}
|
||||
if (~old_valid & data) {
|
||||
pch_pic_update_irq(s, (~old_valid & data), 0);
|
||||
if (~old & data) {
|
||||
pch_pic_update_irq(s, ~old & data, 0);
|
||||
}
|
||||
break;
|
||||
case PCH_PIC_INT_MASK_HI:
|
||||
old = s->int_mask;
|
||||
s->int_mask = get_writew_val(old, data, 1);
|
||||
old_valid = (uint32_t)(old >> 32);
|
||||
int_mask = old_valid & ~data;
|
||||
if (int_mask) {
|
||||
pch_pic_update_irq(s, int_mask << 32, 1);
|
||||
}
|
||||
int_mask = ~old_valid & data;
|
||||
if (int_mask) {
|
||||
pch_pic_update_irq(s, int_mask << 32, 0);
|
||||
}
|
||||
case PCH_PIC_INT_EDGE:
|
||||
s->intedge = (s->intedge & ~mask) | data;
|
||||
break;
|
||||
case PCH_PIC_INT_EDGE_LO:
|
||||
s->intedge = get_writew_val(s->intedge, data, 0);
|
||||
break;
|
||||
case PCH_PIC_INT_EDGE_HI:
|
||||
s->intedge = get_writew_val(s->intedge, data, 1);
|
||||
break;
|
||||
case PCH_PIC_INT_CLEAR_LO:
|
||||
case PCH_PIC_INT_CLEAR:
|
||||
if (s->intedge & data) {
|
||||
s->intirr &= (~data);
|
||||
s->intirr &= ~data;
|
||||
pch_pic_update_irq(s, data, 0);
|
||||
s->intisr &= (~data);
|
||||
s->intisr &= ~data;
|
||||
}
|
||||
break;
|
||||
case PCH_PIC_INT_CLEAR_HI:
|
||||
value <<= 32;
|
||||
if (s->intedge & value) {
|
||||
s->intirr &= (~value);
|
||||
pch_pic_update_irq(s, value, 0);
|
||||
s->intisr &= (~value);
|
||||
}
|
||||
case PCH_PIC_HTMSI_EN:
|
||||
s->htmsi_en = (s->htmsi_en & ~mask) | data;
|
||||
break;
|
||||
case PCH_PIC_HTMSI_EN_LO:
|
||||
s->htmsi_en = get_writew_val(s->htmsi_en, data, 0);
|
||||
case PCH_PIC_AUTO_CTRL0:
|
||||
case PCH_PIC_AUTO_CTRL1:
|
||||
/* Discard auto_ctrl access */
|
||||
break;
|
||||
case PCH_PIC_HTMSI_EN_HI:
|
||||
s->htmsi_en = get_writew_val(s->htmsi_en, data, 1);
|
||||
case PCH_PIC_INT_POL:
|
||||
s->int_polarity = (s->int_polarity & ~mask) | data;
|
||||
break;
|
||||
case PCH_PIC_AUTO_CTRL0_LO:
|
||||
case PCH_PIC_AUTO_CTRL0_HI:
|
||||
case PCH_PIC_AUTO_CTRL1_LO:
|
||||
case PCH_PIC_AUTO_CTRL1_HI:
|
||||
case PCH_PIC_HTMSI_VEC ... PCH_PIC_HTMSI_VEC_END:
|
||||
ptemp = (uint64_t *)(s->htmsi_vector + addr - PCH_PIC_HTMSI_VEC);
|
||||
*ptemp = (*ptemp & ~mask) | data;
|
||||
break;
|
||||
case PCH_PIC_ROUTE_ENTRY ... PCH_PIC_ROUTE_ENTRY_END:
|
||||
ptemp = (uint64_t *)(s->route_entry + addr - PCH_PIC_ROUTE_ENTRY);
|
||||
*ptemp = (*ptemp & ~mask) | data;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"pch_pic_write: Bad address 0x%"PRIx64"\n", addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t loongarch_pch_pic_high_readw(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
static uint64_t loongarch_pch_pic_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
{
|
||||
LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque);
|
||||
uint64_t val = 0;
|
||||
uint32_t offset = addr & 0xfff;
|
||||
|
||||
switch (offset) {
|
||||
case STATUS_LO_START:
|
||||
val = (uint32_t)(s->intisr & (~s->int_mask));
|
||||
switch (size) {
|
||||
case 1:
|
||||
val = pch_pic_read(opaque, addr, UCHAR_MAX);
|
||||
break;
|
||||
case STATUS_HI_START:
|
||||
val = (s->intisr & (~s->int_mask)) >> 32;
|
||||
case 2:
|
||||
val = pch_pic_read(opaque, addr, USHRT_MAX);
|
||||
break;
|
||||
case POL_LO_START:
|
||||
val = (uint32_t)s->int_polarity;
|
||||
case 4:
|
||||
val = pch_pic_read(opaque, addr, UINT_MAX);
|
||||
break;
|
||||
case POL_HI_START:
|
||||
val = s->int_polarity >> 32;
|
||||
case 8:
|
||||
val = pch_pic_read(opaque, addr, UINT64_MAX);
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"loongarch_pch_pic_read: Bad size %d\n", size);
|
||||
break;
|
||||
}
|
||||
|
||||
trace_loongarch_pch_pic_high_readw(size, addr, val);
|
||||
trace_loongarch_pch_pic_read(size, addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void loongarch_pch_pic_high_writew(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned size)
|
||||
static void loongarch_pch_pic_write(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque);
|
||||
uint32_t offset, data = (uint32_t)value;
|
||||
offset = addr & 0xfff;
|
||||
trace_loongarch_pch_pic_write(size, addr, value);
|
||||
|
||||
trace_loongarch_pch_pic_high_writew(size, addr, data);
|
||||
|
||||
switch (offset) {
|
||||
case STATUS_LO_START:
|
||||
s->intisr = get_writew_val(s->intisr, data, 0);
|
||||
switch (size) {
|
||||
case 1:
|
||||
pch_pic_write(opaque, addr, value, UCHAR_MAX);
|
||||
break;
|
||||
case STATUS_HI_START:
|
||||
s->intisr = get_writew_val(s->intisr, data, 1);
|
||||
case 2:
|
||||
pch_pic_write(opaque, addr, value, USHRT_MAX);
|
||||
break;
|
||||
case POL_LO_START:
|
||||
s->int_polarity = get_writew_val(s->int_polarity, data, 0);
|
||||
break;
|
||||
case POL_HI_START:
|
||||
s->int_polarity = get_writew_val(s->int_polarity, data, 1);
|
||||
case 4:
|
||||
pch_pic_write(opaque, addr, value, UINT_MAX);
|
||||
break;
|
||||
case 8:
|
||||
pch_pic_write(opaque, addr, value, UINT64_MAX);
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"loongarch_pch_pic_write: Bad size %d\n", size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t loongarch_pch_pic_readb(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
{
|
||||
LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque);
|
||||
uint64_t val = 0;
|
||||
uint32_t offset = (addr & 0xfff) + PCH_PIC_ROUTE_ENTRY_OFFSET;
|
||||
int64_t offset_tmp;
|
||||
|
||||
switch (offset) {
|
||||
case PCH_PIC_HTMSI_VEC_OFFSET ... PCH_PIC_HTMSI_VEC_END:
|
||||
offset_tmp = offset - PCH_PIC_HTMSI_VEC_OFFSET;
|
||||
if (offset_tmp >= 0 && offset_tmp < 64) {
|
||||
val = s->htmsi_vector[offset_tmp];
|
||||
}
|
||||
break;
|
||||
case PCH_PIC_ROUTE_ENTRY_OFFSET ... PCH_PIC_ROUTE_ENTRY_END:
|
||||
offset_tmp = offset - PCH_PIC_ROUTE_ENTRY_OFFSET;
|
||||
if (offset_tmp >= 0 && offset_tmp < 64) {
|
||||
val = s->route_entry[offset_tmp];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
trace_loongarch_pch_pic_readb(size, addr, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void loongarch_pch_pic_writeb(void *opaque, hwaddr addr,
|
||||
uint64_t data, unsigned size)
|
||||
{
|
||||
LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(opaque);
|
||||
int32_t offset_tmp;
|
||||
uint32_t offset = (addr & 0xfff) + PCH_PIC_ROUTE_ENTRY_OFFSET;
|
||||
|
||||
trace_loongarch_pch_pic_writeb(size, addr, data);
|
||||
|
||||
switch (offset) {
|
||||
case PCH_PIC_HTMSI_VEC_OFFSET ... PCH_PIC_HTMSI_VEC_END:
|
||||
offset_tmp = offset - PCH_PIC_HTMSI_VEC_OFFSET;
|
||||
if (offset_tmp >= 0 && offset_tmp < 64) {
|
||||
s->htmsi_vector[offset_tmp] = (uint8_t)(data & 0xff);
|
||||
}
|
||||
break;
|
||||
case PCH_PIC_ROUTE_ENTRY_OFFSET ... PCH_PIC_ROUTE_ENTRY_END:
|
||||
offset_tmp = offset - PCH_PIC_ROUTE_ENTRY_OFFSET;
|
||||
if (offset_tmp >= 0 && offset_tmp < 64) {
|
||||
s->route_entry[offset_tmp] = (uint8_t)(data & 0xff);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps loongarch_pch_pic_reg32_low_ops = {
|
||||
.read = loongarch_pch_pic_low_readw,
|
||||
.write = loongarch_pch_pic_low_writew,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 8,
|
||||
},
|
||||
.impl = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static const MemoryRegionOps loongarch_pch_pic_reg32_high_ops = {
|
||||
.read = loongarch_pch_pic_high_readw,
|
||||
.write = loongarch_pch_pic_high_writew,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 8,
|
||||
},
|
||||
.impl = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
},
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static const MemoryRegionOps loongarch_pch_pic_reg8_ops = {
|
||||
.read = loongarch_pch_pic_readb,
|
||||
.write = loongarch_pch_pic_writeb,
|
||||
static const MemoryRegionOps loongarch_pch_pic_ops = {
|
||||
.read = loongarch_pch_pic_read,
|
||||
.write = loongarch_pch_pic_write,
|
||||
.valid = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 1,
|
||||
.max_access_size = 8,
|
||||
/*
|
||||
* PCH PIC device would not work correctly if the guest was doing
|
||||
* unaligned access. This might not be a limitation on the real
|
||||
* device but in practice there is no reason for a guest to access
|
||||
* this device unaligned.
|
||||
*/
|
||||
.unaligned = false,
|
||||
},
|
||||
.impl = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 1,
|
||||
.max_access_size = 8,
|
||||
},
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
@ -378,18 +275,10 @@ static void loongarch_pic_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
qdev_init_gpio_out(dev, s->parent_irq, s->irq_num);
|
||||
qdev_init_gpio_in(dev, pch_pic_irq_handler, s->irq_num);
|
||||
memory_region_init_io(&s->iomem32_low, OBJECT(dev),
|
||||
&loongarch_pch_pic_reg32_low_ops,
|
||||
s, PCH_PIC_NAME(.reg32_part1), 0x100);
|
||||
memory_region_init_io(&s->iomem8, OBJECT(dev), &loongarch_pch_pic_reg8_ops,
|
||||
s, PCH_PIC_NAME(.reg8), 0x2a0);
|
||||
memory_region_init_io(&s->iomem32_high, OBJECT(dev),
|
||||
&loongarch_pch_pic_reg32_high_ops,
|
||||
s, PCH_PIC_NAME(.reg32_part2), 0xc60);
|
||||
sysbus_init_mmio(sbd, &s->iomem32_low);
|
||||
sysbus_init_mmio(sbd, &s->iomem8);
|
||||
sysbus_init_mmio(sbd, &s->iomem32_high);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(dev),
|
||||
&loongarch_pch_pic_ops,
|
||||
s, TYPE_LOONGARCH_PIC, VIRT_PCH_REG_SIZE);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
||||
static void loongarch_pic_class_init(ObjectClass *klass, const void *data)
|
||||
|
|
|
@ -49,6 +49,19 @@ static void loongarch_pic_common_reset_hold(Object *obj, ResetType type)
|
|||
LoongArchPICCommonState *s = LOONGARCH_PIC_COMMON(obj);
|
||||
int i;
|
||||
|
||||
/*
|
||||
* With Loongson 7A1000 user manual
|
||||
* Chapter 5.2 "Description of Interrupt-related Registers"
|
||||
*
|
||||
* Interrupt controller identification register 1
|
||||
* Bit 24-31 Interrupt Controller ID
|
||||
* Interrupt controller identification register 2
|
||||
* Bit 0-7 Interrupt Controller version number
|
||||
* Bit 16-23 The number of interrupt sources supported
|
||||
*/
|
||||
s->id.desc.id = PCH_PIC_INT_ID_VAL;
|
||||
s->id.desc.version = PCH_PIC_INT_ID_VER;
|
||||
s->id.desc.irq_num = s->irq_num - 1;
|
||||
s->int_mask = UINT64_MAX;
|
||||
s->htmsi_en = 0x0;
|
||||
s->intedge = 0x0;
|
||||
|
|
|
@ -314,12 +314,8 @@ loongson_ipi_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x
|
|||
loongson_ipi_write(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%"PRIx64
|
||||
# loongarch_pch_pic.c
|
||||
loongarch_pch_pic_irq_handler(int irq, int level) "irq %d level %d"
|
||||
loongarch_pch_pic_low_readw(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
|
||||
loongarch_pch_pic_low_writew(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
|
||||
loongarch_pch_pic_high_readw(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
|
||||
loongarch_pch_pic_high_writew(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
|
||||
loongarch_pch_pic_readb(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
|
||||
loongarch_pch_pic_writeb(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
|
||||
loongarch_pch_pic_read(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
|
||||
loongarch_pch_pic_write(unsigned size, uint64_t addr, uint64_t val) "size: %u addr: 0x%"PRIx64 "val: 0x%" PRIx64
|
||||
|
||||
# loongarch_pch_msi.c
|
||||
loongarch_msi_set_irq(int irq_num) "set msi irq %d"
|
||||
|
|
|
@ -235,6 +235,45 @@ static int64_t load_loongarch_linux_image(const char *filename,
|
|||
return size;
|
||||
}
|
||||
|
||||
static ram_addr_t alloc_initrd_memory(struct loongarch_boot_info *info,
|
||||
uint64_t advice_start, ssize_t rd_size)
|
||||
{
|
||||
hwaddr base, ram_size, gap, low_end;
|
||||
ram_addr_t initrd_end, initrd_start;
|
||||
|
||||
base = VIRT_LOWMEM_BASE;
|
||||
gap = VIRT_LOWMEM_SIZE;
|
||||
initrd_start = advice_start;
|
||||
initrd_end = initrd_start + rd_size;
|
||||
|
||||
ram_size = info->ram_size;
|
||||
low_end = base + MIN(ram_size, gap);
|
||||
if (initrd_end <= low_end) {
|
||||
return initrd_start;
|
||||
}
|
||||
|
||||
if (ram_size <= gap) {
|
||||
error_report("The low memory too small for initial ram disk '%s',"
|
||||
"You need to expand the ram",
|
||||
info->initrd_filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to load initrd in the high memory
|
||||
*/
|
||||
ram_size -= gap;
|
||||
initrd_start = VIRT_HIGHMEM_BASE;
|
||||
if (rd_size <= ram_size) {
|
||||
return initrd_start;
|
||||
}
|
||||
|
||||
error_report("The high memory too small for initial ram disk '%s',"
|
||||
"You need to expand the ram",
|
||||
info->initrd_filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int64_t load_kernel_info(struct loongarch_boot_info *info)
|
||||
{
|
||||
uint64_t kernel_entry, kernel_low, kernel_high;
|
||||
|
@ -263,15 +302,10 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info)
|
|||
initrd_size = get_image_size(info->initrd_filename);
|
||||
if (initrd_size > 0) {
|
||||
initrd_offset = ROUND_UP(kernel_high + 4 * kernel_size, 64 * KiB);
|
||||
|
||||
if (initrd_offset + initrd_size > info->ram_size) {
|
||||
error_report("memory too small for initial ram disk '%s'",
|
||||
info->initrd_filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
initrd_size = load_image_targphys(info->initrd_filename, initrd_offset,
|
||||
info->ram_size - initrd_offset);
|
||||
initrd_offset = alloc_initrd_memory(info, initrd_offset,
|
||||
initrd_size);
|
||||
initrd_size = load_image_targphys(info->initrd_filename,
|
||||
initrd_offset, initrd_size);
|
||||
}
|
||||
|
||||
if (initrd_size == (target_ulong)-1) {
|
||||
|
|
|
@ -429,12 +429,6 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
|
|||
sysbus_realize_and_unref(d, &error_fatal);
|
||||
memory_region_add_subregion(get_system_memory(), VIRT_IOAPIC_REG_BASE,
|
||||
sysbus_mmio_get_region(d, 0));
|
||||
memory_region_add_subregion(get_system_memory(),
|
||||
VIRT_IOAPIC_REG_BASE + PCH_PIC_ROUTE_ENTRY_OFFSET,
|
||||
sysbus_mmio_get_region(d, 1));
|
||||
memory_region_add_subregion(get_system_memory(),
|
||||
VIRT_IOAPIC_REG_BASE + PCH_PIC_INT_STATUS_LO,
|
||||
sysbus_mmio_get_region(d, 2));
|
||||
|
||||
/* Connect pch_pic irqs to extioi */
|
||||
for (i = 0; i < num; i++) {
|
||||
|
|
|
@ -10,44 +10,43 @@
|
|||
#include "hw/pci-host/ls7a.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define PCH_PIC_INT_ID_VAL 0x7000000UL
|
||||
#define PCH_PIC_INT_ID_VER 0x1UL
|
||||
#define PCH_PIC_INT_ID_LO 0x00
|
||||
#define PCH_PIC_INT_ID_HI 0x04
|
||||
#define PCH_PIC_INT_MASK_LO 0x20
|
||||
#define PCH_PIC_INT_MASK_HI 0x24
|
||||
#define PCH_PIC_HTMSI_EN_LO 0x40
|
||||
#define PCH_PIC_HTMSI_EN_HI 0x44
|
||||
#define PCH_PIC_INT_EDGE_LO 0x60
|
||||
#define PCH_PIC_INT_EDGE_HI 0x64
|
||||
#define PCH_PIC_INT_CLEAR_LO 0x80
|
||||
#define PCH_PIC_INT_CLEAR_HI 0x84
|
||||
#define PCH_PIC_AUTO_CTRL0_LO 0xc0
|
||||
#define PCH_PIC_AUTO_CTRL0_HI 0xc4
|
||||
#define PCH_PIC_AUTO_CTRL1_LO 0xe0
|
||||
#define PCH_PIC_AUTO_CTRL1_HI 0xe4
|
||||
#define PCH_PIC_ROUTE_ENTRY_OFFSET 0x100
|
||||
#define PCH_PIC_INT_ID 0x00
|
||||
#define PCH_PIC_INT_ID_VAL 0x7
|
||||
#define PCH_PIC_INT_ID_VER 0x1
|
||||
#define PCH_PIC_INT_MASK 0x20
|
||||
#define PCH_PIC_HTMSI_EN 0x40
|
||||
#define PCH_PIC_INT_EDGE 0x60
|
||||
#define PCH_PIC_INT_CLEAR 0x80
|
||||
#define PCH_PIC_AUTO_CTRL0 0xc0
|
||||
#define PCH_PIC_AUTO_CTRL1 0xe0
|
||||
#define PCH_PIC_ROUTE_ENTRY 0x100
|
||||
#define PCH_PIC_ROUTE_ENTRY_END 0x13f
|
||||
#define PCH_PIC_HTMSI_VEC_OFFSET 0x200
|
||||
#define PCH_PIC_HTMSI_VEC 0x200
|
||||
#define PCH_PIC_HTMSI_VEC_END 0x23f
|
||||
#define PCH_PIC_INT_STATUS_LO 0x3a0
|
||||
#define PCH_PIC_INT_STATUS_HI 0x3a4
|
||||
#define PCH_PIC_INT_POL_LO 0x3e0
|
||||
#define PCH_PIC_INT_POL_HI 0x3e4
|
||||
|
||||
#define STATUS_LO_START 0
|
||||
#define STATUS_HI_START 0x4
|
||||
#define POL_LO_START 0x40
|
||||
#define POL_HI_START 0x44
|
||||
#define PCH_PIC_INT_STATUS 0x3a0
|
||||
#define PCH_PIC_INT_POL 0x3e0
|
||||
|
||||
#define TYPE_LOONGARCH_PIC_COMMON "loongarch_pic_common"
|
||||
OBJECT_DECLARE_TYPE(LoongArchPICCommonState,
|
||||
LoongArchPICCommonClass, LOONGARCH_PIC_COMMON)
|
||||
|
||||
union LoongArchPIC_ID {
|
||||
struct {
|
||||
uint8_t _reserved_0[3];
|
||||
uint8_t id;
|
||||
uint8_t version;
|
||||
uint8_t _reserved_1;
|
||||
uint8_t irq_num;
|
||||
uint8_t _reserved_2;
|
||||
} QEMU_PACKED desc;
|
||||
uint64_t data;
|
||||
};
|
||||
|
||||
struct LoongArchPICCommonState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
qemu_irq parent_irq[64];
|
||||
union LoongArchPIC_ID id; /* 0x00 interrupt ID register */
|
||||
uint64_t int_mask; /* 0x020 interrupt mask register */
|
||||
uint64_t htmsi_en; /* 0x040 1=msi */
|
||||
uint64_t intedge; /* 0x060 edge=1 level=0 */
|
||||
|
@ -66,9 +65,7 @@ struct LoongArchPICCommonState {
|
|||
uint8_t route_entry[64]; /* 0x100 - 0x138 */
|
||||
uint8_t htmsi_vector[64]; /* 0x200 - 0x238 */
|
||||
|
||||
MemoryRegion iomem32_low;
|
||||
MemoryRegion iomem32_high;
|
||||
MemoryRegion iomem8;
|
||||
MemoryRegion iomem;
|
||||
unsigned int irq_num;
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue