MIPS patches queue

- Extract nanoMIPS, microMIPS, Code Compaction from translate.c
 - Allow PCI config accesses smaller than 32-bit on Bonito64 device
 - Fix migration of g364fb device on Jazz Magnum
 - Fix dp8393x PROM checksum on Jazz Magnum and Quadra 800
 - Map the UART devices unconditionally on Jazz Magnum
 - Add functional test booting Linux on the Fuloong 2E
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmDfMnMACgkQ4+MsLN6t
 wN71nhAArpyoJ5mTkt54wAxZwxvqjWAyesvogV4pLIvOyNJmQcExY/Ly8Qb5dbDg
 2PEhCpDU7GlT7oCfgh7O5KrEjnqVfmHQzzbvQ0Ygq9kL5hdjaSSlHB/yeirU7CR1
 cMQXfj9kvRVa5Oayt3L+kiKgTA0f1vbGmnveiFxJKJupyVDtursstD3nSZCThSVL
 FWdFJbqLzvTY3cQqLBVq7jEnN7LzSYeYnq8Tvri0nuwoBwLJY382IljqsQZrGHzr
 Bbya3KFInMrQK5VAM0pOkfvPYXZmtJ8i8VuR6S+IdICiZ+61sknKRUq5z09/4NXA
 HaxarWO/fv07qd7q6Z2+i5Q6fiDrV4p2qfHeddM4Xwqvu8O98EPhaBE3veLOiNgr
 VxgkJFslI1gstje31qqvNjFxB+cOIBYjWTlIVu1xOuOKGWMjMT+9XcVLseweA2rT
 H/nTKnWTAiJ/mxT4KIv59SS0ZQa4QJ3CjYr26AcQ9YrJ9vCMay8rLPEn0iVlhB2H
 ZyW4Be84ynEvuAvvuWt1AXvFjT41Zqj4Px1M6Pa15e9eV6guiW1KV13Thb45gJqt
 LTQtoME83r3gUhQOcoZaowYh6ffCbjtW3eAcTZP3Zu7fOeBjSye+CvS9NJMtK3Vj
 0/YjtqGPUvjNy4sR9VqkRRPMZpHftMTRILxaFm8Y5tlThkAydw0=
 =rR+B
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/philmd/tags/mips-20210702' into staging

MIPS patches queue

- Extract nanoMIPS, microMIPS, Code Compaction from translate.c
- Allow PCI config accesses smaller than 32-bit on Bonito64 device
- Fix migration of g364fb device on Jazz Magnum
- Fix dp8393x PROM checksum on Jazz Magnum and Quadra 800
- Map the UART devices unconditionally on Jazz Magnum
- Add functional test booting Linux on the Fuloong 2E

# gpg: Signature made Fri 02 Jul 2021 16:36:19 BST
# gpg:                using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE
# gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [full]
# Primary key fingerprint: FAAB E75E 1291 7221 DCFD  6BB2 E3E3 2C2C DEAD C0DE

* remotes/philmd/tags/mips-20210702:
  hw/mips/jazz: Map the UART devices unconditionally
  hw/mips/jazz: specify correct endian for dp8393x device
  hw/m68k/q800: fix PROM checksum and MAC address storage
  qemu/bitops.h: add bitrev8 implementation
  dp8393x: remove onboard PROM containing MAC address and checksum
  hw/m68k/q800: move PROM and checksum calculation from dp8393x device to board
  hw/mips/jazz: move PROM and checksum calculation from dp8393x device to board
  dp8393x: convert to trace-events
  dp8393x: checkpatch fixes
  g364fb: add VMStateDescription for G364SysBusState
  g364fb: use RAM memory region for framebuffer
  tests/acceptance: Test Linux on the Fuloong 2E machine
  hw/pci-host/bonito: Allow PCI config accesses smaller than 32-bit
  hw/pci-host/bonito: Trace PCI config accesses smaller than 32-bit
  target/mips: Extract nanoMIPS ISA translation routines
  target/mips: Extract the microMIPS ISA translation routines
  target/mips: Extract Code Compaction ASE translation routines
  target/mips: Add declarations for generic TCG helpers

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-07-04 14:04:12 +01:00
commit 711c0418c8
15 changed files with 9603 additions and 9456 deletions

View file

@ -246,6 +246,7 @@ K: ^Subject:.*(?i)mips
MIPS TCG CPUs (nanoMIPS ISA)
S: Orphan
F: disas/nanomips.*
F: target/mips/tcg/*nanomips*
NiosII TCG CPUs
M: Chris Wulff <crwulff@gmail.com>
@ -1177,6 +1178,7 @@ F: hw/isa/vt82c686.c
F: hw/pci-host/bonito.c
F: hw/usb/vt82c686-uhci-pci.c
F: include/hw/isa/vt82c686.h
F: tests/acceptance/machine_mips_fuloong2e.py
Loongson-3 virtual platforms
M: Huacai Chen <chenhuacai@kernel.org>

View file

@ -22,6 +22,7 @@
#include "hw/hw.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
#include "ui/console.h"
@ -33,7 +34,6 @@
typedef struct G364State {
/* hardware */
uint8_t *vram;
uint32_t vram_size;
qemu_irq irq;
MemoryRegion mem_vram;
@ -125,7 +125,7 @@ static void g364fb_draw_graphic8(G364State *s)
xcursor = ycursor = -65;
}
vram = s->vram + s->top_of_screen;
vram = memory_region_get_ram_ptr(&s->mem_vram) + s->top_of_screen;
/* XXX: out of range in vram? */
data_display = dd = surface_data(surface);
snap = memory_region_snapshot_and_clear_dirty(&s->mem_vram, 0, s->vram_size,
@ -274,6 +274,8 @@ static inline void g364fb_invalidate_display(void *opaque)
static void g364fb_reset(G364State *s)
{
uint8_t *vram = memory_region_get_ram_ptr(&s->mem_vram);
qemu_irq_lower(s->irq);
memset(s->color_palette, 0, sizeof(s->color_palette));
@ -283,7 +285,7 @@ static void g364fb_reset(G364State *s)
s->ctla = 0;
s->top_of_screen = 0;
s->width = s->height = 0;
memset(s->vram, 0, s->vram_size);
memset(vram, 0, s->vram_size);
g364fb_invalidate_display(s);
}
@ -450,11 +452,10 @@ static int g364fb_post_load(void *opaque, int version_id)
static const VMStateDescription vmstate_g364fb = {
.name = "g364fb",
.version_id = 1,
.minimum_version_id = 1,
.version_id = 2,
.minimum_version_id = 2,
.post_load = g364fb_post_load,
.fields = (VMStateField[]) {
VMSTATE_VBUFFER_UINT32(vram, G364State, 1, NULL, vram_size),
VMSTATE_BUFFER_UNSAFE(color_palette, G364State, 0, 256 * 3),
VMSTATE_BUFFER_UNSAFE(cursor_palette, G364State, 0, 9),
VMSTATE_UINT16_ARRAY(cursor, G364State, 512),
@ -474,15 +475,12 @@ static const GraphicHwOps g364fb_ops = {
static void g364fb_init(DeviceState *dev, G364State *s)
{
s->vram = g_malloc0(s->vram_size);
s->con = graphic_console_init(dev, 0, &g364fb_ops, s);
memory_region_init_io(&s->mem_ctrl, OBJECT(dev), &g364fb_ctrl_ops, s,
"ctrl", 0x180000);
memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram",
s->vram_size, s->vram);
vmstate_register_ram(&s->mem_vram, dev);
memory_region_init_ram(&s->mem_vram, NULL, "g364fb.vram", s->vram_size,
&error_fatal);
memory_region_set_log(&s->mem_vram, true, DIRTY_MEMORY_VGA);
}
@ -519,6 +517,16 @@ static Property g364fb_sysbus_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
static const VMStateDescription vmstate_g364fb_sysbus = {
.name = "g364fb-sysbus",
.version_id = 2,
.minimum_version_id = 2,
.fields = (VMStateField[]) {
VMSTATE_STRUCT(g364, G364SysBusState, 2, vmstate_g364fb, G364State),
VMSTATE_END_OF_LIST()
}
};
static void g364fb_sysbus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@ -527,7 +535,7 @@ static void g364fb_sysbus_class_init(ObjectClass *klass, void *data)
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
dc->desc = "G364 framebuffer";
dc->reset = g364fb_sysbus_reset;
dc->vmsd = &vmstate_g364fb;
dc->vmsd = &vmstate_g364fb_sysbus;
device_class_set_props(dc, g364fb_sysbus_properties);
}

View file

@ -70,6 +70,8 @@
#define NUBUS_SUPER_SLOT_BASE 0x60000000
#define NUBUS_SLOT_BASE 0xf0000000
#define SONIC_PROM_SIZE 0x1000
/*
* the video base, whereas it a Nubus address,
* is needed by the kernel to have early display and
@ -211,8 +213,10 @@ static void q800_init(MachineState *machine)
int32_t initrd_size;
MemoryRegion *rom;
MemoryRegion *io;
MemoryRegion *dp8393x_prom = g_new(MemoryRegion, 1);
uint8_t *prom;
const int io_slice_nb = (IO_SIZE / IO_SLICE) - 1;
int i;
int i, checksum;
ram_addr_t ram_size = machine->ram_size;
const char *kernel_filename = machine->kernel_filename;
const char *initrd_filename = machine->initrd_filename;
@ -319,9 +323,22 @@ static void q800_init(MachineState *machine)
sysbus = SYS_BUS_DEVICE(dev);
sysbus_realize_and_unref(sysbus, &error_fatal);
sysbus_mmio_map(sysbus, 0, SONIC_BASE);
sysbus_mmio_map(sysbus, 1, SONIC_PROM_BASE);
sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(glue, 2));
memory_region_init_rom(dp8393x_prom, NULL, "dp8393x-q800.prom",
SONIC_PROM_SIZE, &error_fatal);
memory_region_add_subregion(get_system_memory(), SONIC_PROM_BASE,
dp8393x_prom);
/* Add MAC address with valid checksum to PROM */
prom = memory_region_get_ram_ptr(dp8393x_prom);
checksum = 0;
for (i = 0; i < 6; i++) {
prom[i] = bitrev8(nd_table[0].macaddr.a[i]);
checksum ^= prom[i];
}
prom[7] = 0xff - checksum;
/* SCC */
dev = qdev_new(TYPE_ESCC);

View file

@ -119,12 +119,14 @@ static const MemoryRegionOps dma_dummy_ops = {
#define MAGNUM_BIOS_SIZE \
(BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
#define SONIC_PROM_SIZE 0x1000
static void mips_jazz_init(MachineState *machine,
enum jazz_model_e jazz_model)
{
MemoryRegion *address_space = get_system_memory();
char *filename;
int bios_size, n;
int bios_size, n, big_endian;
Clock *cpuclk;
MIPSCPU *cpu;
MIPSCPUClass *mcc;
@ -137,6 +139,7 @@ static void mips_jazz_init(MachineState *machine,
MemoryRegion *rtc = g_new(MemoryRegion, 1);
MemoryRegion *i8042 = g_new(MemoryRegion, 1);
MemoryRegion *dma_dummy = g_new(MemoryRegion, 1);
MemoryRegion *dp8393x_prom = g_new(MemoryRegion, 1);
NICInfo *nd;
DeviceState *dev, *rc4030;
SysBusDevice *sysbus;
@ -155,6 +158,12 @@ static void mips_jazz_init(MachineState *machine,
[JAZZ_PICA61] = {33333333, 4},
};
#ifdef TARGET_WORDS_BIGENDIAN
big_endian = 1;
#else
big_endian = 0;
#endif
if (machine->ram_size > 256 * MiB) {
error_report("RAM size more than 256Mb is not supported");
exit(EXIT_FAILURE);
@ -228,6 +237,10 @@ static void mips_jazz_init(MachineState *machine,
NULL, "dummy_dma", 0x1000);
memory_region_add_subregion(address_space, 0x8000d000, dma_dummy);
memory_region_init_rom(dp8393x_prom, NULL, "dp8393x-jazz.prom",
SONIC_PROM_SIZE, &error_fatal);
memory_region_add_subregion(address_space, 0x8000b000, dp8393x_prom);
/* ISA bus: IO space at 0x90000000, mem space at 0x91000000 */
memory_region_init(isa_io, NULL, "isa-io", 0x00010000);
memory_region_init(isa_mem, NULL, "isa-mem", 0x01000000);
@ -275,18 +288,33 @@ static void mips_jazz_init(MachineState *machine,
nd->model = g_strdup("dp83932");
}
if (strcmp(nd->model, "dp83932") == 0) {
int checksum, i;
uint8_t *prom;
qemu_check_nic_model(nd, "dp83932");
dev = qdev_new("dp8393x");
qdev_set_nic_properties(dev, nd);
qdev_prop_set_uint8(dev, "it_shift", 2);
qdev_prop_set_bit(dev, "big_endian", big_endian > 0);
object_property_set_link(OBJECT(dev), "dma_mr",
OBJECT(rc4030_dma_mr), &error_abort);
sysbus = SYS_BUS_DEVICE(dev);
sysbus_realize_and_unref(sysbus, &error_fatal);
sysbus_mmio_map(sysbus, 0, 0x80001000);
sysbus_mmio_map(sysbus, 1, 0x8000b000);
sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 4));
/* Add MAC address with valid checksum to PROM */
prom = memory_region_get_ram_ptr(dp8393x_prom);
checksum = 0;
for (i = 0; i < 6; i++) {
prom[i] = nd->macaddr.a[i];
checksum += prom[i];
if (checksum > 0xff) {
checksum = (checksum + 1) & 0xff;
}
}
prom[7] = 0xff - checksum;
break;
} else if (is_help_option(nd->model)) {
error_report("Supported NICs: dp83932");
@ -333,16 +361,12 @@ static void mips_jazz_init(MachineState *machine,
memory_region_add_subregion(address_space, 0x80005000, i8042);
/* Serial ports */
if (serial_hd(0)) {
serial_mm_init(address_space, 0x80006000, 0,
qdev_get_gpio_in(rc4030, 8), 8000000 / 16,
serial_hd(0), DEVICE_NATIVE_ENDIAN);
}
if (serial_hd(1)) {
serial_mm_init(address_space, 0x80007000, 0,
qdev_get_gpio_in(rc4030, 9), 8000000 / 16,
serial_hd(1), DEVICE_NATIVE_ENDIAN);
}
serial_mm_init(address_space, 0x80006000, 0,
qdev_get_gpio_in(rc4030, 8), 8000000 / 16,
serial_hd(0), DEVICE_NATIVE_ENDIAN);
serial_mm_init(address_space, 0x80007000, 0,
qdev_get_gpio_in(rc4030, 9), 8000000 / 16,
serial_hd(1), DEVICE_NATIVE_ENDIAN);
/* Parallel port */
if (parallel_hds[0])

View file

@ -28,15 +28,9 @@
#include "qemu/timer.h"
#include <zlib.h>
#include "qom/object.h"
#include "trace.h"
//#define DEBUG_SONIC
#define SONIC_PROM_SIZE 0x1000
#ifdef DEBUG_SONIC
#define DPRINTF(fmt, ...) \
do { printf("sonic: " fmt , ## __VA_ARGS__); } while (0)
static const char* reg_names[] = {
static const char *reg_names[] = {
"CR", "DCR", "RCR", "TCR", "IMR", "ISR", "UTDA", "CTDA",
"TPS", "TFC", "TSA0", "TSA1", "TFS", "URDA", "CRDA", "CRBA0",
"CRBA1", "RBWC0", "RBWC1", "EOBC", "URRA", "RSA", "REA", "RRP",
@ -45,12 +39,6 @@ static const char* reg_names[] = {
"SR", "WT0", "WT1", "RSC", "CRCT", "FAET", "MPT", "MDT",
"0x30", "0x31", "0x32", "0x33", "0x34", "0x35", "0x36", "0x37",
"0x38", "0x39", "0x3a", "0x3b", "0x3c", "0x3d", "0x3e", "DCR2" };
#else
#define DPRINTF(fmt, ...) do {} while (0)
#endif
#define SONIC_ERROR(fmt, ...) \
do { printf("sonic ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
#define SONIC_CR 0x00
#define SONIC_DCR 0x01
@ -161,15 +149,12 @@ struct dp8393xState {
bool big_endian;
bool last_rba_is_full;
qemu_irq irq;
#ifdef DEBUG_SONIC
int irq_level;
#endif
QEMUTimer *watchdog;
int64_t wt_last_update;
NICConf conf;
NICState *nic;
MemoryRegion mmio;
MemoryRegion prom;
/* Registers */
uint8_t cam[16][6];
@ -185,7 +170,8 @@ struct dp8393xState {
AddressSpace as;
};
/* Accessor functions for values which are formed by
/*
* Accessor functions for values which are formed by
* concatenating two 16 bit device registers. By putting these
* in their own functions with a uint32_t return type we avoid the
* pitfall of implicit sign extension where ((x << 16) | y) is a
@ -269,16 +255,14 @@ static void dp8393x_update_irq(dp8393xState *s)
{
int level = (s->regs[SONIC_IMR] & s->regs[SONIC_ISR]) ? 1 : 0;
#ifdef DEBUG_SONIC
if (level != s->irq_level) {
s->irq_level = level;
if (level) {
DPRINTF("raise irq, isr is 0x%04x\n", s->regs[SONIC_ISR]);
trace_dp8393x_raise_irq(s->regs[SONIC_ISR]);
} else {
DPRINTF("lower irq\n");
trace_dp8393x_lower_irq();
}
}
#endif
qemu_set_irq(s->irq, level);
}
@ -301,9 +285,9 @@ static void dp8393x_do_load_cam(dp8393xState *s)
s->cam[index][3] = dp8393x_get(s, width, 2) >> 8;
s->cam[index][4] = dp8393x_get(s, width, 3) & 0xff;
s->cam[index][5] = dp8393x_get(s, width, 3) >> 8;
DPRINTF("load cam[%d] with %02x%02x%02x%02x%02x%02x\n", index,
s->cam[index][0], s->cam[index][1], s->cam[index][2],
s->cam[index][3], s->cam[index][4], s->cam[index][5]);
trace_dp8393x_load_cam(index, s->cam[index][0], s->cam[index][1],
s->cam[index][2], s->cam[index][3],
s->cam[index][4], s->cam[index][5]);
/* Move to next entry */
s->regs[SONIC_CDC]--;
s->regs[SONIC_CDP] += size;
@ -314,7 +298,7 @@ static void dp8393x_do_load_cam(dp8393xState *s)
address_space_read(&s->as, dp8393x_cdp(s),
MEMTXATTRS_UNSPECIFIED, s->data, size);
s->regs[SONIC_CE] = dp8393x_get(s, width, 0);
DPRINTF("load cam done. cam enable mask 0x%04x\n", s->regs[SONIC_CE]);
trace_dp8393x_load_cam_done(s->regs[SONIC_CE]);
/* Done */
s->regs[SONIC_CR] &= ~SONIC_CR_LCAM;
@ -337,9 +321,8 @@ static void dp8393x_do_read_rra(dp8393xState *s)
s->regs[SONIC_CRBA1] = dp8393x_get(s, width, 1);
s->regs[SONIC_RBWC0] = dp8393x_get(s, width, 2);
s->regs[SONIC_RBWC1] = dp8393x_get(s, width, 3);
DPRINTF("CRBA0/1: 0x%04x/0x%04x, RBWC0/1: 0x%04x/0x%04x\n",
s->regs[SONIC_CRBA0], s->regs[SONIC_CRBA1],
s->regs[SONIC_RBWC0], s->regs[SONIC_RBWC1]);
trace_dp8393x_read_rra_regs(s->regs[SONIC_CRBA0], s->regs[SONIC_CRBA1],
s->regs[SONIC_RBWC0], s->regs[SONIC_RBWC1]);
/* Go to next entry */
s->regs[SONIC_RRP] += size;
@ -350,8 +333,7 @@ static void dp8393x_do_read_rra(dp8393xState *s)
}
/* Warn the host if CRBA now has the last available resource */
if (s->regs[SONIC_RRP] == s->regs[SONIC_RWP])
{
if (s->regs[SONIC_RRP] == s->regs[SONIC_RWP]) {
s->regs[SONIC_ISR] |= SONIC_ISR_RBE;
dp8393x_update_irq(s);
}
@ -364,7 +346,8 @@ static void dp8393x_do_software_reset(dp8393xState *s)
{
timer_del(s->watchdog);
s->regs[SONIC_CR] &= ~(SONIC_CR_LCAM | SONIC_CR_RRRA | SONIC_CR_TXP | SONIC_CR_HTX);
s->regs[SONIC_CR] &= ~(SONIC_CR_LCAM | SONIC_CR_RRRA | SONIC_CR_TXP |
SONIC_CR_HTX);
s->regs[SONIC_CR] |= SONIC_CR_RST | SONIC_CR_RXDIS;
}
@ -443,7 +426,7 @@ static void dp8393x_do_transmit_packets(dp8393xState *s)
/* Read memory */
size = sizeof(uint16_t) * 6 * width;
s->regs[SONIC_TTDA] = s->regs[SONIC_CTDA];
DPRINTF("Transmit packet at %08x\n", dp8393x_ttda(s));
trace_dp8393x_transmit_packet(dp8393x_ttda(s));
address_space_read(&s->as, dp8393x_ttda(s) + sizeof(uint16_t) * width,
MEMTXATTRS_UNSPECIFIED, s->data, size);
tx_len = 0;
@ -490,13 +473,15 @@ static void dp8393x_do_transmit_packets(dp8393xState *s)
/* Handle Ethernet checksum */
if (!(s->regs[SONIC_TCR] & SONIC_TCR_CRCI)) {
/* Don't append FCS there, to look like slirp packets
* which don't have one */
/*
* Don't append FCS there, to look like slirp packets
* which don't have one
*/
} else {
/* Remove existing FCS */
tx_len -= 4;
if (tx_len < 0) {
SONIC_ERROR("tx_len is %d\n", tx_len);
trace_dp8393x_transmit_txlen_error(tx_len);
break;
}
}
@ -558,26 +543,34 @@ static void dp8393x_do_command(dp8393xState *s, uint16_t command)
s->regs[SONIC_CR] |= (command & SONIC_CR_MASK);
if (command & SONIC_CR_HTX)
if (command & SONIC_CR_HTX) {
dp8393x_do_halt_transmission(s);
if (command & SONIC_CR_TXP)
}
if (command & SONIC_CR_TXP) {
dp8393x_do_transmit_packets(s);
if (command & SONIC_CR_RXDIS)
}
if (command & SONIC_CR_RXDIS) {
dp8393x_do_receiver_disable(s);
if (command & SONIC_CR_RXEN)
}
if (command & SONIC_CR_RXEN) {
dp8393x_do_receiver_enable(s);
if (command & SONIC_CR_STP)
}
if (command & SONIC_CR_STP) {
dp8393x_do_stop_timer(s);
if (command & SONIC_CR_ST)
}
if (command & SONIC_CR_ST) {
dp8393x_do_start_timer(s);
if (command & SONIC_CR_RST)
}
if (command & SONIC_CR_RST) {
dp8393x_do_software_reset(s);
}
if (command & SONIC_CR_RRRA) {
dp8393x_do_read_rra(s);
s->regs[SONIC_CR] &= ~SONIC_CR_RRRA;
}
if (command & SONIC_CR_LCAM)
if (command & SONIC_CR_LCAM) {
dp8393x_do_load_cam(s);
}
}
static uint64_t dp8393x_read(void *opaque, hwaddr addr, unsigned int size)
@ -587,27 +580,27 @@ static uint64_t dp8393x_read(void *opaque, hwaddr addr, unsigned int size)
uint16_t val = 0;
switch (reg) {
/* Update data before reading it */
case SONIC_WT0:
case SONIC_WT1:
dp8393x_update_wt_regs(s);
val = s->regs[reg];
break;
/* Accept read to some registers only when in reset mode */
case SONIC_CAP2:
case SONIC_CAP1:
case SONIC_CAP0:
if (s->regs[SONIC_CR] & SONIC_CR_RST) {
val = s->cam[s->regs[SONIC_CEP] & 0xf][2* (SONIC_CAP0 - reg) + 1] << 8;
val |= s->cam[s->regs[SONIC_CEP] & 0xf][2* (SONIC_CAP0 - reg)];
}
break;
/* All other registers have no special contrainst */
default:
val = s->regs[reg];
/* Update data before reading it */
case SONIC_WT0:
case SONIC_WT1:
dp8393x_update_wt_regs(s);
val = s->regs[reg];
break;
/* Accept read to some registers only when in reset mode */
case SONIC_CAP2:
case SONIC_CAP1:
case SONIC_CAP0:
if (s->regs[SONIC_CR] & SONIC_CR_RST) {
val = s->cam[s->regs[SONIC_CEP] & 0xf][2 * (SONIC_CAP0 - reg) + 1] << 8;
val |= s->cam[s->regs[SONIC_CEP] & 0xf][2 * (SONIC_CAP0 - reg)];
}
break;
/* All other registers have no special contraints */
default:
val = s->regs[reg];
}
DPRINTF("read 0x%04x from reg %s\n", val, reg_names[reg]);
trace_dp8393x_read(reg, reg_names[reg], val, size);
return s->big_endian ? val << 16 : val;
}
@ -619,78 +612,78 @@ static void dp8393x_write(void *opaque, hwaddr addr, uint64_t data,
int reg = addr >> s->it_shift;
uint32_t val = s->big_endian ? data >> 16 : data;
DPRINTF("write 0x%04x to reg %s\n", (uint16_t)val, reg_names[reg]);
trace_dp8393x_write(reg, reg_names[reg], val, size);
switch (reg) {
/* Command register */
case SONIC_CR:
dp8393x_do_command(s, val);
break;
/* Prevent write to read-only registers */
case SONIC_CAP2:
case SONIC_CAP1:
case SONIC_CAP0:
case SONIC_SR:
case SONIC_MDT:
DPRINTF("writing to reg %d invalid\n", reg);
break;
/* Accept write to some registers only when in reset mode */
case SONIC_DCR:
if (s->regs[SONIC_CR] & SONIC_CR_RST) {
s->regs[reg] = val & 0xbfff;
} else {
DPRINTF("writing to DCR invalid\n");
}
break;
case SONIC_DCR2:
if (s->regs[SONIC_CR] & SONIC_CR_RST) {
s->regs[reg] = val & 0xf017;
} else {
DPRINTF("writing to DCR2 invalid\n");
}
break;
/* 12 lower bytes are Read Only */
case SONIC_TCR:
s->regs[reg] = val & 0xf000;
break;
/* 9 lower bytes are Read Only */
case SONIC_RCR:
s->regs[reg] = val & 0xffe0;
break;
/* Ignore most significant bit */
case SONIC_IMR:
s->regs[reg] = val & 0x7fff;
dp8393x_update_irq(s);
break;
/* Clear bits by writing 1 to them */
case SONIC_ISR:
val &= s->regs[reg];
s->regs[reg] &= ~val;
if (val & SONIC_ISR_RBE) {
dp8393x_do_read_rra(s);
}
dp8393x_update_irq(s);
break;
/* The guest is required to store aligned pointers here */
case SONIC_RSA:
case SONIC_REA:
case SONIC_RRP:
case SONIC_RWP:
if (s->regs[SONIC_DCR] & SONIC_DCR_DW) {
s->regs[reg] = val & 0xfffc;
} else {
s->regs[reg] = val & 0xfffe;
}
break;
/* Invert written value for some registers */
case SONIC_CRCT:
case SONIC_FAET:
case SONIC_MPT:
s->regs[reg] = val ^ 0xffff;
break;
/* All other registers have no special contrainst */
default:
s->regs[reg] = val;
/* Command register */
case SONIC_CR:
dp8393x_do_command(s, val);
break;
/* Prevent write to read-only registers */
case SONIC_CAP2:
case SONIC_CAP1:
case SONIC_CAP0:
case SONIC_SR:
case SONIC_MDT:
trace_dp8393x_write_invalid(reg);
break;
/* Accept write to some registers only when in reset mode */
case SONIC_DCR:
if (s->regs[SONIC_CR] & SONIC_CR_RST) {
s->regs[reg] = val & 0xbfff;
} else {
trace_dp8393x_write_invalid_dcr("DCR");
}
break;
case SONIC_DCR2:
if (s->regs[SONIC_CR] & SONIC_CR_RST) {
s->regs[reg] = val & 0xf017;
} else {
trace_dp8393x_write_invalid_dcr("DCR2");
}
break;
/* 12 lower bytes are Read Only */
case SONIC_TCR:
s->regs[reg] = val & 0xf000;
break;
/* 9 lower bytes are Read Only */
case SONIC_RCR:
s->regs[reg] = val & 0xffe0;
break;
/* Ignore most significant bit */
case SONIC_IMR:
s->regs[reg] = val & 0x7fff;
dp8393x_update_irq(s);
break;
/* Clear bits by writing 1 to them */
case SONIC_ISR:
val &= s->regs[reg];
s->regs[reg] &= ~val;
if (val & SONIC_ISR_RBE) {
dp8393x_do_read_rra(s);
}
dp8393x_update_irq(s);
break;
/* The guest is required to store aligned pointers here */
case SONIC_RSA:
case SONIC_REA:
case SONIC_RRP:
case SONIC_RWP:
if (s->regs[SONIC_DCR] & SONIC_DCR_DW) {
s->regs[reg] = val & 0xfffc;
} else {
s->regs[reg] = val & 0xfffe;
}
break;
/* Invert written value for some registers */
case SONIC_CRCT:
case SONIC_FAET:
case SONIC_MPT:
s->regs[reg] = val ^ 0xffff;
break;
/* All other registers have no special contrainst */
default:
s->regs[reg] = val;
}
if (reg == SONIC_WT0 || reg == SONIC_WT1) {
@ -747,17 +740,18 @@ static int dp8393x_receive_filter(dp8393xState *s, const uint8_t * buf,
}
/* Check broadcast */
if ((s->regs[SONIC_RCR] & SONIC_RCR_BRD) && !memcmp(buf, bcast, sizeof(bcast))) {
if ((s->regs[SONIC_RCR] & SONIC_RCR_BRD) &&
!memcmp(buf, bcast, sizeof(bcast))) {
return SONIC_RCR_BC;
}
/* Check CAM */
for (i = 0; i < 16; i++) {
if (s->regs[SONIC_CE] & (1 << i)) {
/* Entry enabled */
if (!memcmp(buf, s->cam[i], sizeof(s->cam[i]))) {
return 0;
}
/* Entry enabled */
if (!memcmp(buf, s->cam[i], sizeof(s->cam[i]))) {
return 0;
}
}
}
@ -791,7 +785,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
}
if (padded_len > dp8393x_rbwc(s) * 2) {
DPRINTF("oversize packet, pkt_size is %d\n", pkt_size);
trace_dp8393x_receive_oversize(pkt_size);
s->regs[SONIC_ISR] |= SONIC_ISR_RBAE;
dp8393x_update_irq(s);
s->regs[SONIC_RCR] |= SONIC_RCR_LPKT;
@ -800,7 +794,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
packet_type = dp8393x_receive_filter(s, buf, pkt_size);
if (packet_type < 0) {
DPRINTF("packet not for netcard\n");
trace_dp8393x_receive_not_netcard();
return -1;
}
@ -838,7 +832,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
checksum = cpu_to_le32(crc32(0, buf, pkt_size));
/* Put packet into RBA */
DPRINTF("Receive packet at %08x\n", dp8393x_crba(s));
trace_dp8393x_receive_packet(dp8393x_crba(s));
address = dp8393x_crba(s);
address_space_write(&s->as, address, MEMTXATTRS_UNSPECIFIED,
buf, pkt_size);
@ -876,7 +870,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
}
/* Write status to memory */
DPRINTF("Write status at %08x\n", dp8393x_crda(s));
trace_dp8393x_receive_write_status(dp8393x_crda(s));
dp8393x_put(s, width, 0, s->regs[SONIC_RCR]); /* status */
dp8393x_put(s, width, 1, rx_len); /* byte count */
dp8393x_put(s, width, 2, s->regs[SONIC_TRBA0]); /* pkt_ptr0 */
@ -938,7 +932,8 @@ static void dp8393x_reset(DeviceState *dev)
s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux/mips */
s->regs[SONIC_CR] = SONIC_CR_RST | SONIC_CR_STP | SONIC_CR_RXDIS;
s->regs[SONIC_DCR] &= ~(SONIC_DCR_EXBUS | SONIC_DCR_LBR);
s->regs[SONIC_RCR] &= ~(SONIC_RCR_LB0 | SONIC_RCR_LB1 | SONIC_RCR_BRD | SONIC_RCR_RNT);
s->regs[SONIC_RCR] &= ~(SONIC_RCR_LB0 | SONIC_RCR_LB1 | SONIC_RCR_BRD |
SONIC_RCR_RNT);
s->regs[SONIC_TCR] |= SONIC_TCR_NCRS | SONIC_TCR_PTX;
s->regs[SONIC_TCR] &= ~SONIC_TCR_BCM;
s->regs[SONIC_IMR] = 0;
@ -968,16 +963,12 @@ static void dp8393x_instance_init(Object *obj)
dp8393xState *s = DP8393X(obj);
sysbus_init_mmio(sbd, &s->mmio);
sysbus_init_mmio(sbd, &s->prom);
sysbus_init_irq(sbd, &s->irq);
}
static void dp8393x_realize(DeviceState *dev, Error **errp)
{
dp8393xState *s = DP8393X(dev);
int i, checksum;
uint8_t *prom;
Error *local_err = NULL;
address_space_init(&s->as, s->dma_mr, "dp8393x");
memory_region_init_io(&s->mmio, OBJECT(dev), &dp8393x_ops, s,
@ -988,23 +979,6 @@ static void dp8393x_realize(DeviceState *dev, Error **errp)
qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s);
memory_region_init_rom(&s->prom, OBJECT(dev), "dp8393x-prom",
SONIC_PROM_SIZE, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
}
prom = memory_region_get_ram_ptr(&s->prom);
checksum = 0;
for (i = 0; i < 6; i++) {
prom[i] = s->conf.macaddr.a[i];
checksum += prom[i];
if (checksum > 0xff) {
checksum = (checksum + 1) & 0xff;
}
}
prom[7] = 0xff - checksum;
}
static const VMStateDescription vmstate_dp8393x = {

View file

@ -436,3 +436,20 @@ npcm7xx_emc_received_packet(uint32_t len) "Received %u byte packet"
npcm7xx_emc_rx_done(uint32_t crxdsa) "RX done, CRXDSA=0x%x"
npcm7xx_emc_reg_read(int emc_num, uint32_t result, const char *name, int regno) "emc%d: 0x%x = reg[%s/%d]"
npcm7xx_emc_reg_write(int emc_num, const char *name, int regno, uint32_t value) "emc%d: reg[%s/%d] = 0x%x"
# dp8398x.c
dp8393x_raise_irq(int isr) "raise irq, isr is 0x%04x"
dp8393x_lower_irq(void) "lower irq"
dp8393x_load_cam(int idx, int cam0, int cam1, int cam2, int cam3, int cam4, int cam5) "load cam[%d] with 0x%02x0x%02x0x%02x0x%02x0x%02x0x%02x"
dp8393x_load_cam_done(int cen) "load cam done. cam enable mask 0x%04x"
dp8393x_read_rra_regs(int crba0, int crba1, int rbwc0, int rbwc1) "CRBA0/1: 0x%04x/0x%04x, RBWC0/1: 0x%04x/0x%04x"
dp8393x_transmit_packet(int ttda) "Transmit packet at 0x%"PRIx32
dp8393x_transmit_txlen_error(int len) "tx_len is %d"
dp8393x_read(int reg, const char *name, int val, int size) "reg=0x%x [%s] val=0x%04x size=%d"
dp8393x_write(int reg, const char *name, int val, int size) "reg=0x%x [%s] val=0x%04x size=%d"
dp8393x_write_invalid(int reg) "writing to reg %d invalid"
dp8393x_write_invalid_dcr(const char *name) "writing to %s invalid"
dp8393x_receive_oversize(int size) "oversize packet, pkt_size is %d"
dp8393x_receive_not_netcard(void) "packet not for netcard"
dp8393x_receive_packet(int crba) "Receive packet at 0x%"PRIx32
dp8393x_receive_write_status(int crba) "Write status at 0x%"PRIx32

View file

@ -52,6 +52,7 @@
#include "hw/misc/unimp.h"
#include "hw/registerfields.h"
#include "qom/object.h"
#include "trace.h"
/* #define DEBUG_BONITO */
@ -185,7 +186,8 @@ FIELD(BONGENCFG, PCIQUEUE, 12, 1)
#define BONITO_PCICONF_IDSEL_OFFSET 11
#define BONITO_PCICONF_FUN_MASK 0x700 /* [10:8] */
#define BONITO_PCICONF_FUN_OFFSET 8
#define BONITO_PCICONF_REG_MASK 0xFC
#define BONITO_PCICONF_REG_MASK_DS (~3) /* Per datasheet */
#define BONITO_PCICONF_REG_MASK_HW 0xff /* As seen running PMON */
#define BONITO_PCICONF_REG_OFFSET 0
@ -464,7 +466,7 @@ static uint32_t bonito_sbridge_pciaddr(void *opaque, hwaddr addr)
BONITO_PCICONF_IDSEL_OFFSET;
devno = ctz32(idsel);
funno = (cfgaddr & BONITO_PCICONF_FUN_MASK) >> BONITO_PCICONF_FUN_OFFSET;
regno = (cfgaddr & BONITO_PCICONF_REG_MASK) >> BONITO_PCICONF_REG_OFFSET;
regno = (cfgaddr & BONITO_PCICONF_REG_MASK_HW) >> BONITO_PCICONF_REG_OFFSET;
if (idsel == 0) {
error_report("error in bonito pci config address 0x" TARGET_FMT_plx
@ -495,6 +497,9 @@ static void bonito_spciconf_write(void *opaque, hwaddr addr, uint64_t val,
if (pciaddr == 0xffffffff) {
return;
}
if (addr & ~BONITO_PCICONF_REG_MASK_DS) {
trace_bonito_spciconf_small_access(addr, size);
}
/* set the pci address in s->config_reg */
phb->config_reg = (pciaddr) | (1u << 31);
@ -521,6 +526,9 @@ static uint64_t bonito_spciconf_read(void *opaque, hwaddr addr, unsigned size)
if (pciaddr == 0xffffffff) {
return MAKE_64BIT_MASK(0, size * 8);
}
if (addr & ~BONITO_PCICONF_REG_MASK_DS) {
trace_bonito_spciconf_small_access(addr, size);
}
/* set the pci address in s->config_reg */
phb->config_reg = (pciaddr) | (1u << 31);

View file

@ -1,5 +1,8 @@
# See docs/devel/tracing.rst for syntax documentation.
# bonito.c
bonito_spciconf_small_access(uint64_t addr, unsigned size) "PCI config address is smaller then 32-bit, addr: 0x%"PRIx64", size: %u"
# grackle.c
grackle_set_irq(int irq_num, int level) "set_irq num %d level %d"

View file

@ -618,4 +618,26 @@ static inline uint64_t half_unshuffle64(uint64_t x)
return x;
}
/**
* bitrev8:
* @x: 8-bit value to be reversed
*
* Given an input value with bits::
*
* ABCDEFGH
*
* return the value with its bits reversed from left to right::
*
* HGFEDCBA
*
* Returns: the bit-reversed value.
*/
static inline uint8_t bitrev8(uint8_t x)
{
x = ((x >> 1) & 0x55) | ((x << 1) & 0xaa);
x = ((x >> 2) & 0x33) | ((x << 2) & 0xcc);
x = (x >> 4) | (x << 4) ;
return x;
}
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -146,6 +146,11 @@ void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg);
void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg);
int get_fp_bit(int cc);
void gen_ldxs(DisasContext *ctx, int base, int index, int rd);
void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int bp);
void gen_addiupc(DisasContext *ctx, int rx, int imm,
int is_64_bit, int extended);
/*
* Address Computation and Large Constant Instructions
*/

View file

@ -0,0 +1,42 @@
# Functional tests for the Lemote Fuloong-2E machine.
#
# Copyright (c) 2019 Philippe Mathieu-Daudé <f4bug@amsat.org>
#
# This work is licensed under the terms of the GNU GPL, version 2 or later.
# See the COPYING file in the top-level directory.
#
# SPDX-License-Identifier: GPL-2.0-or-later
import os
from avocado import skipUnless
from avocado_qemu import Test
from avocado_qemu import wait_for_console_pattern
class MipsFuloong2e(Test):
timeout = 60
@skipUnless(os.getenv('AVOCADO_ALLOW_UNTRUSTED_CODE'), 'untrusted code')
@skipUnless(os.getenv('RESCUE_YL_PATH'), 'RESCUE_YL_PATH not available')
def test_linux_kernel_isa_serial(self):
"""
:avocado: tags=arch:mips64el
:avocado: tags=machine:fuloong2e
:avocado: tags=endian:little
:avocado: tags=device:bonito64
:avocado: tags=device:via686b
"""
# Recovery system for the Yeeloong laptop
# (enough to test the fuloong2e southbridge, accessing its ISA bus)
# http://dev.lemote.com/files/resource/download/rescue/rescue-yl
kernel_hash = 'ec4d1bd89a8439c41033ca63db60160cc6d6f09a'
kernel_path = self.fetch_asset('file://' + os.getenv('RESCUE_YL_PATH'),
asset_hash=kernel_hash)
self.vm.set_console()
self.vm.add_args('-kernel', kernel_path)
self.vm.launch()
wait_for_console_pattern(self, 'Linux version 2.6.27.7lemote')
cpu_revision = 'CPU revision is: 00006302 (ICT Loongson-2)'
wait_for_console_pattern(self, cpu_revision)