diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-09-07 21:50:29 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-09-07 21:50:29 +0100 |
commit | e4c4f7db607f6e668beb595bbd0aecadf6ddd058 (patch) | |
tree | 6939a64991dd4946162eadf6a158ec1113b12d50 | |
parent | e11bd71f89649da3cff439c030d2ccac0cc914e3 (diff) | |
parent | 32a2b033f0a406c0dd4cc7375367ee63cc36789a (diff) |
Merge remote-tracking branch 'remotes/hdeller/tags/target-hppa-pull-request' into staging
hppa power button support, graphics updates and firmware fixes
# gpg: Signature made Mon 07 Sep 2020 20:09:49 BST
# gpg: using EDDSA key BCE9123E1AD29F07C049BBDEF712B510A23A0F5F
# gpg: Good signature from "Helge Deller <deller@gmx.de>" [unknown]
# gpg: aka "Helge Deller <deller@kernel.org>" [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: 4544 8228 2CD9 10DB EF3D 25F8 3E5F 3D04 A7A2 4603
# Subkey fingerprint: BCE9 123E 1AD2 9F07 C049 BBDE F712 B510 A23A 0F5F
* remotes/hdeller/tags/target-hppa-pull-request:
hw/display/artist: Allow screen size up to 2048 lines
hw/display/artist: Refactor x/y coordination extraction
hw/display/artist: Verify artist screen resolution
target/hppa: Fix boot with old Linux installation CDs
hw/hppa: Add power button emulation
hw/hppa: Tell SeaBIOS port address of fw_cfg
hw/hppa: Change fw_cfg port address
hw/hppa: Store boot device in fw_cfg section
hw/hppa: Make number of TLB and BTLB entries configurable
seabios-hppa: Update SeaBIOS to hppa-qemu-5.2-2 tag
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | hw/display/artist.c | 43 | ||||
-rw-r--r-- | hw/hppa/hppa_hardware.h | 3 | ||||
-rw-r--r-- | hw/hppa/machine.c | 56 | ||||
-rw-r--r-- | pc-bios/hppa-firmware.img | bin | 783192 -> 785696 bytes | |||
m--------- | roms/seabios-hppa | 0 | ||||
-rw-r--r-- | target/hppa/cpu.h | 5 | ||||
-rw-r--r-- | target/hppa/insns.decode | 10 |
7 files changed, 94 insertions, 23 deletions
diff --git a/hw/display/artist.c b/hw/display/artist.c index 71982559c6..955296d3d8 100644 --- a/hw/display/artist.c +++ b/hw/display/artist.c @@ -192,6 +192,10 @@ static const char *artist_reg_name(uint64_t addr) } #undef REG_NAME +/* artist has a fixed line length of 2048 bytes. */ +#define ADDR_TO_Y(addr) extract32(addr, 11, 11) +#define ADDR_TO_X(addr) extract32(addr, 0, 11) + static int16_t artist_get_x(uint32_t reg) { return reg >> 16; @@ -348,13 +352,13 @@ static void artist_invalidate_cursor(ARTISTState *s) y, s->cursor_height); } -static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x, +static void vram_bit_write(ARTISTState *s, int posy, bool incr_x, int size, uint32_t data) { struct vram_buffer *buf; uint32_t vram_bitmask = s->vram_bitmask; int mask, i, pix_count, pix_length; - unsigned int offset, width; + unsigned int posx, offset, width; uint8_t *data8, *p; pix_count = vram_write_pix_per_transfer(s); @@ -366,6 +370,8 @@ static void vram_bit_write(ARTISTState *s, int posx, int posy, bool incr_x, if (s->cmap_bm_access) { offset = s->vram_pos; } else { + posx = ADDR_TO_X(s->vram_pos >> 2); + posy += ADDR_TO_Y(s->vram_pos >> 2); offset = posy * width + posx; } @@ -858,7 +864,6 @@ static void artist_reg_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { ARTISTState *s = opaque; - int posx, posy; int width, height; trace_artist_reg_write(size, addr, artist_reg_name(addr & ~3ULL), val); @@ -881,16 +886,12 @@ static void artist_reg_write(void *opaque, hwaddr addr, uint64_t val, break; case VRAM_WRITE_INCR_Y: - posx = (s->vram_pos >> 2) & 0x7ff; - posy = (s->vram_pos >> 13) & 0x3ff; - vram_bit_write(s, posx, posy + s->vram_char_y++, false, size, val); + vram_bit_write(s, s->vram_char_y++, false, size, val); break; case VRAM_WRITE_INCR_X: case VRAM_WRITE_INCR_X2: - posx = (s->vram_pos >> 2) & 0x7ff; - posy = (s->vram_pos >> 13) & 0x3ff; - vram_bit_write(s, posx, posy + s->vram_char_y, true, size, val); + vram_bit_write(s, s->vram_char_y, true, size, val); break; case VRAM_IDX: @@ -1156,8 +1157,7 @@ static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val, { ARTISTState *s = opaque; struct vram_buffer *buf; - int posy = (addr >> 11) & 0x3ff; - int posx = addr & 0x7ff; + unsigned int posy, posx; unsigned int offset; trace_artist_vram_write(size, addr, val); @@ -1170,6 +1170,9 @@ static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val, } buf = vram_write_buffer(s); + posy = ADDR_TO_Y(addr); + posx = ADDR_TO_X(addr); + if (!buf->size) { return; } @@ -1212,7 +1215,7 @@ static uint64_t artist_vram_read(void *opaque, hwaddr addr, unsigned size) ARTISTState *s = opaque; struct vram_buffer *buf; uint64_t val; - int posy, posx; + unsigned int posy, posx; if (s->cmap_bm_access) { buf = &s->vram_buffer[ARTIST_BUFFER_CMAP]; @@ -1229,8 +1232,8 @@ static uint64_t artist_vram_read(void *opaque, hwaddr addr, unsigned size) return 0; } - posy = (addr >> 13) & 0x3ff; - posx = (addr >> 2) & 0x7ff; + posy = ADDR_TO_Y(addr); + posx = ADDR_TO_X(addr); if (posy > buf->height || posx > buf->width) { return 0; @@ -1374,6 +1377,18 @@ static void artist_realizefn(DeviceState *dev, Error **errp) struct vram_buffer *buf; hwaddr offset = 0; + if (s->width > 2048 || s->height > 2048) { + error_report("artist: screen size can not exceed 2048 x 2048 pixel."); + s->width = MIN(s->width, 2048); + s->height = MIN(s->height, 2048); + } + + if (s->width < 640 || s->height < 480) { + error_report("artist: minimum screen size is 640 x 480 pixel."); + s->width = MAX(s->width, 640); + s->height = MAX(s->height, 480); + } + memory_region_init(&s->mem_as_root, OBJECT(dev), "artist", ~0ull); address_space_init(&s->as, &s->mem_as_root, "artist"); diff --git a/hw/hppa/hppa_hardware.h b/hw/hppa/hppa_hardware.h index cdb7fa6240..bc258895c9 100644 --- a/hw/hppa/hppa_hardware.h +++ b/hw/hppa/hppa_hardware.h @@ -38,8 +38,7 @@ #define PORT_PCI_CMD (PCI_HPA + DINO_PCI_ADDR) #define PORT_PCI_DATA (PCI_HPA + DINO_CONFIG_DATA) -/* QEMU fw_cfg interface port */ -#define QEMU_FW_CFG_IO_BASE (MEMORY_HPA + 0x80) +#define FW_CFG_IO_BASE 0xfffa0000 #define PORT_SERIAL1 (DINO_UART_HPA + 0x800) #define PORT_SERIAL2 (LASI_UART_HPA + 0x800) diff --git a/hw/hppa/machine.c b/hw/hppa/machine.c index 90aeefe2a4..d5164457ee 100644 --- a/hw/hppa/machine.c +++ b/hw/hppa/machine.c @@ -12,6 +12,7 @@ #include "qemu/error-report.h" #include "sysemu/reset.h" #include "sysemu/sysemu.h" +#include "sysemu/runstate.h" #include "hw/rtc/mc146818rtc.h" #include "hw/timer/i8254.h" #include "hw/char/serial.h" @@ -27,6 +28,30 @@ #define MIN_SEABIOS_HPPA_VERSION 1 /* require at least this fw version */ +#define HPA_POWER_BUTTON (FIRMWARE_END - 0x10) + +static void hppa_powerdown_req(Notifier *n, void *opaque) +{ + hwaddr soft_power_reg = HPA_POWER_BUTTON; + uint32_t val; + + val = ldl_be_phys(&address_space_memory, soft_power_reg); + if ((val >> 8) == 0) { + /* immediately shut down when under hardware control */ + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); + return; + } + + /* clear bit 31 to indicate that the power switch was pressed. */ + val &= ~1; + stl_be_phys(&address_space_memory, soft_power_reg, val); +} + +static Notifier hppa_system_powerdown_notifier = { + .notify = hppa_powerdown_req +}; + + static ISABus *hppa_isa_bus(void) { ISABus *isa_bus; @@ -58,12 +83,18 @@ static uint64_t cpu_hppa_to_phys(void *opaque, uint64_t addr) static HPPACPU *cpu[HPPA_MAX_CPUS]; static uint64_t firmware_entry; +static void fw_cfg_boot_set(void *opaque, const char *boot_device, + Error **errp) +{ + fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); +} + static FWCfgState *create_fw_cfg(MachineState *ms) { FWCfgState *fw_cfg; uint64_t val; - fw_cfg = fw_cfg_init_mem(QEMU_FW_CFG_IO_BASE, QEMU_FW_CFG_IO_BASE + 4); + fw_cfg = fw_cfg_init_mem(FW_CFG_IO_BASE, FW_CFG_IO_BASE + 4); fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, ms->smp.cpus); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, HPPA_MAX_CPUS); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, ram_size); @@ -72,6 +103,21 @@ static FWCfgState *create_fw_cfg(MachineState *ms) fw_cfg_add_file(fw_cfg, "/etc/firmware-min-version", g_memdup(&val, sizeof(val)), sizeof(val)); + val = cpu_to_le64(HPPA_TLB_ENTRIES); + fw_cfg_add_file(fw_cfg, "/etc/cpu/tlb_entries", + g_memdup(&val, sizeof(val)), sizeof(val)); + + val = cpu_to_le64(HPPA_BTLB_ENTRIES); + fw_cfg_add_file(fw_cfg, "/etc/cpu/btlb_entries", + g_memdup(&val, sizeof(val)), sizeof(val)); + + val = cpu_to_le64(HPA_POWER_BUTTON); + fw_cfg_add_file(fw_cfg, "/etc/power-button-addr", + g_memdup(&val, sizeof(val)), sizeof(val)); + + fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ms->boot_order[0]); + qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); + return fw_cfg; } @@ -160,6 +206,9 @@ static void machine_hppa_init(MachineState *machine) } } + /* register power switch emulation */ + qemu_register_powerdown_notifier(&hppa_system_powerdown_notifier); + /* Load firmware. Given that this is not "real" firmware, but one explicitly written for the emulation, we might as well load it directly from an ELF image. */ @@ -273,6 +322,9 @@ static void machine_hppa_init(MachineState *machine) /* tell firmware how many SMP CPUs to present in inventory table */ cpu[0]->env.gr[21] = smp_cpus; + + /* tell firmware fw_cfg port */ + cpu[0]->env.gr[19] = FW_CFG_IO_BASE; } static void hppa_machine_reset(MachineState *ms) @@ -300,6 +352,8 @@ static void hppa_machine_reset(MachineState *ms) cpu[0]->env.gr[24] = 'c'; /* gr22/gr23 unused, no initrd while reboot. */ cpu[0]->env.gr[21] = smp_cpus; + /* tell firmware fw_cfg port */ + cpu[0]->env.gr[19] = FW_CFG_IO_BASE; } diff --git a/pc-bios/hppa-firmware.img b/pc-bios/hppa-firmware.img Binary files differindex f0f8d0e164..4ba8c7f8b8 100644 --- a/pc-bios/hppa-firmware.img +++ b/pc-bios/hppa-firmware.img diff --git a/roms/seabios-hppa b/roms/seabios-hppa -Subproject 4ff7639e2b86d5775fa7d5cd0dbfa4d3a385a70 +Subproject 73b740f77190643b2ada5ee97a9a108c6ef2a37 diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 801a4fb1ba..fb6c59d075 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -196,9 +196,12 @@ struct CPUHPPAState { target_ureg shadow[7]; /* shadow registers */ /* ??? The number of entries isn't specified by the architecture. */ +#define HPPA_TLB_ENTRIES 256 +#define HPPA_BTLB_ENTRIES 0 + /* ??? Implement a unified itlb/dtlb for the moment. */ /* ??? We should use a more intelligent data structure. */ - hppa_tlb_entry tlb[256]; + hppa_tlb_entry tlb[HPPA_TLB_ENTRIES]; uint32_t tlb_last; }; diff --git a/target/hppa/insns.decode b/target/hppa/insns.decode index f0dd71dd08..dceaad65e9 100644 --- a/target/hppa/insns.decode +++ b/target/hppa/insns.decode @@ -149,9 +149,9 @@ lci 000001 ----- ----- -- 01001100 0 t:5 # Arith/Log #### -andcm 000010 ..... ..... .... 000000 0 ..... @rrr_cf -and 000010 ..... ..... .... 001000 0 ..... @rrr_cf -or 000010 ..... ..... .... 001001 0 ..... @rrr_cf +andcm 000010 ..... ..... .... 000000 - ..... @rrr_cf +and 000010 ..... ..... .... 001000 - ..... @rrr_cf +or 000010 ..... ..... .... 001001 - ..... @rrr_cf xor 000010 ..... ..... .... 001010 0 ..... @rrr_cf uxor 000010 ..... ..... .... 001110 0 ..... @rrr_cf ds 000010 ..... ..... .... 010001 0 ..... @rrr_cf @@ -161,13 +161,13 @@ uaddcm_tc 000010 ..... ..... .... 100111 0 ..... @rrr_cf dcor 000010 ..... 00000 .... 101110 0 ..... @rr_cf dcor_i 000010 ..... 00000 .... 101111 0 ..... @rr_cf -add 000010 ..... ..... .... 0110.. 0 ..... @rrr_cf_sh +add 000010 ..... ..... .... 0110.. - ..... @rrr_cf_sh add_l 000010 ..... ..... .... 1010.. 0 ..... @rrr_cf_sh add_tsv 000010 ..... ..... .... 1110.. 0 ..... @rrr_cf_sh add_c 000010 ..... ..... .... 011100 0 ..... @rrr_cf_sh0 add_c_tsv 000010 ..... ..... .... 111100 0 ..... @rrr_cf_sh0 -sub 000010 ..... ..... .... 010000 0 ..... @rrr_cf +sub 000010 ..... ..... .... 010000 - ..... @rrr_cf sub_tsv 000010 ..... ..... .... 110000 0 ..... @rrr_cf sub_tc 000010 ..... ..... .... 010011 0 ..... @rrr_cf sub_tsv_tc 000010 ..... ..... .... 110011 0 ..... @rrr_cf |