mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging
Patch queue for ppc - 2014-09-08
Alexander Graf (11):
PPC: KVM: Fix g3beige and mac99 when HV is loaded
PPC: mac99: Move NVRAM to page boundary when necessary
KVM: Add helper to run KVM_CHECK_EXTENSION on vm fd
PPC: KVM: Use vm check_extension for pv hcall
PPC: mac99: Fix core99 timer frequency
PPC: mac_nvram: Remove unused functions
PPC: mac_nvram: Allow 2 and 4 byte accesses
PPC: mac_nvram: Split NVRAM into OF and OSX parts
PPC: Mac: Move tbfreq into local variable
PPC: Cuda: Use cuda timer to expose tbfreq to guest
PPC: Fix default config ordering and add eTSEC for ppc64
Alexey Kardashevskiy (7):
spapr: Move DT memory node rendering to a helper
spapr: Use DT memory node rendering helper for other nodes
spapr: Refactor spapr_populate_memory() to allow memoryless nodes
spapr: Split memory nodes to power-of-two blocks
spapr: Add a helper for node0_size calculation
spapr: Fix ibm, associativity for memory nodes
spapr_pci: Fix config space corruption
Anton Blanchard (2):
spapr-vlan: Don't touch last entry in buffer list
hypervisor property clashes with hypervisor node
Benjamin Herrenschmidt (2):
loader: Add load_image_size() to replace load_image()
spapr: Locate RTAS and device-tree based on real RMA
Bharat Bhushan (4):
ppc: debug stub: Get trap instruction opcode from KVM
ppc: synchronize excp_vectors for injecting exception
ppc: Add software breakpoint support
ppc: Add hw breakpoint watchpoint support
Gonglei (1):
spapr: fix possible memory leak
Greg Kurz (1):
spapr_pci: map the MSI window in each PHB
Nikunj A Dadhania (3):
ppc: spapr-rtas - implement os-term rtas call
spapr: add uuid/host details to device tree
ppc/spapr: Fix MAX_CPUS to 255
Peter Maydell (1):
hw/ppc/spapr_hcall.c: Fix typo in function names
Tom Musta (20):
linux-user: Fix Stack Pointer Bug in PPC setup_rt_frame
linux-user: Split PPC Trampoline Encoding from Register Save
linux-user: Enable Signal Handlers on PPC64
linux-user: Properly Dereference PPC64 ELFv1 Signal Handler Pointer
linux-user: Implement do_setcontext for PPC64
linux-user: Handle PPC64 ELFv2 Function Pointers
target-ppc: Bug Fix: rlwinm
target-ppc: Bug Fix: rlwnm
target-ppc: Bug Fix: rlwimi
target-ppc: Bug Fix: mullwo
target-ppc: Bug Fix: mullw
target-ppc: Bug Fix: mulldo OV Detection
target-ppc: Bug Fix: srawi
target-ppc: Bug Fix: srad
target-ppc: Special Case of rlwimi Should Use Deposit
target-ppc: Optimize rlwinm MB=0 ME=31
target-ppc: Optimize rlwnm MB=0 ME=31
target-ppc: Clean Up mullw
target-ppc: Clean up mullwo
target-ppc: Implement mulldo with TCG
# gpg: Signature made Mon 08 Sep 2014 11:51:15 BST using RSA key ID 03FEDC60
# gpg: Can't check signature: public key not found
* remotes/agraf/tags/signed-ppc-for-upstream: (52 commits)
hypervisor property clashes with hypervisor node
PPC: Fix default config ordering and add eTSEC for ppc64
spapr_pci: map the MSI window in each PHB
target-ppc: Implement mulldo with TCG
target-ppc: Clean up mullwo
target-ppc: Clean Up mullw
target-ppc: Optimize rlwnm MB=0 ME=31
target-ppc: Optimize rlwinm MB=0 ME=31
target-ppc: Special Case of rlwimi Should Use Deposit
spapr-vlan: Don't touch last entry in buffer list
spapr_pci: Fix config space corruption
PPC: Cuda: Use cuda timer to expose tbfreq to guest
PPC: Mac: Move tbfreq into local variable
PPC: mac_nvram: Split NVRAM into OF and OSX parts
PPC: mac_nvram: Allow 2 and 4 byte accesses
PPC: mac_nvram: Remove unused functions
PPC: mac99: Fix core99 timer frequency
PPC: KVM: Use vm check_extension for pv hcall
KVM: Add helper to run KVM_CHECK_EXTENSION on vm fd
target-ppc: Bug Fix: srad
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -45,8 +45,8 @@ CONFIG_PREP=y
|
||||
CONFIG_MAC=y
|
||||
CONFIG_E500=y
|
||||
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
|
||||
CONFIG_ETSEC=y
|
||||
CONFIG_LIBDECNUMBER=y
|
||||
# For PReP
|
||||
CONFIG_MC146818RTC=y
|
||||
CONFIG_ETSEC=y
|
||||
CONFIG_ISA_TESTDEV=y
|
||||
CONFIG_LIBDECNUMBER=y
|
||||
|
||||
@@ -46,6 +46,8 @@ CONFIG_PREP=y
|
||||
CONFIG_MAC=y
|
||||
CONFIG_E500=y
|
||||
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
|
||||
CONFIG_ETSEC=y
|
||||
CONFIG_LIBDECNUMBER=y
|
||||
# For pSeries
|
||||
CONFIG_XICS=$(CONFIG_PSERIES)
|
||||
CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
|
||||
@@ -58,4 +60,3 @@ CONFIG_I82374=y
|
||||
CONFIG_I8257=y
|
||||
CONFIG_MC146818RTC=y
|
||||
CONFIG_ISA_TESTDEV=y
|
||||
CONFIG_LIBDECNUMBER=y
|
||||
|
||||
@@ -89,6 +89,27 @@ int load_image(const char *filename, uint8_t *addr)
|
||||
return size;
|
||||
}
|
||||
|
||||
/* return the size or -1 if error */
|
||||
ssize_t load_image_size(const char *filename, void *addr, size_t size)
|
||||
{
|
||||
int fd;
|
||||
ssize_t actsize;
|
||||
|
||||
fd = open(filename, O_RDONLY | O_BINARY);
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
actsize = read(fd, addr, size);
|
||||
if (actsize < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return actsize;
|
||||
}
|
||||
|
||||
/* read()-like version */
|
||||
ssize_t read_targphys(const char *name,
|
||||
int fd, hwaddr dst_addr, size_t nbytes)
|
||||
|
||||
+20
-3
@@ -123,13 +123,22 @@ static void cuda_update_irq(CUDAState *s)
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t get_tb(uint64_t freq)
|
||||
{
|
||||
return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
|
||||
freq, get_ticks_per_sec());
|
||||
}
|
||||
|
||||
static unsigned int get_counter(CUDATimer *s)
|
||||
{
|
||||
int64_t d;
|
||||
unsigned int counter;
|
||||
uint64_t tb_diff;
|
||||
|
||||
/* Reverse of the tb calculation algorithm that Mac OS X uses on bootup. */
|
||||
tb_diff = get_tb(s->frequency) - s->load_time;
|
||||
d = (tb_diff * 0xBF401675E5DULL) / (s->frequency << 24);
|
||||
|
||||
d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->load_time,
|
||||
CUDA_TIMER_FREQ, get_ticks_per_sec());
|
||||
if (s->index == 0) {
|
||||
/* the timer goes down from latch to -1 (period of latch + 2) */
|
||||
if (d <= (s->counter_value + 1)) {
|
||||
@@ -147,7 +156,7 @@ static unsigned int get_counter(CUDATimer *s)
|
||||
static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
|
||||
{
|
||||
CUDA_DPRINTF("T%d.counter=%d\n", 1 + (ti->timer == NULL), val);
|
||||
ti->load_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
ti->load_time = get_tb(s->frequency);
|
||||
ti->counter_value = val;
|
||||
cuda_timer_update(s, ti, ti->load_time);
|
||||
}
|
||||
@@ -688,6 +697,8 @@ static void cuda_realizefn(DeviceState *dev, Error **errp)
|
||||
struct tm tm;
|
||||
|
||||
s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer1, s);
|
||||
s->timers[0].frequency = s->frequency;
|
||||
s->timers[1].frequency = s->frequency;
|
||||
|
||||
qemu_get_timedate(&tm, 0);
|
||||
s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
|
||||
@@ -713,6 +724,11 @@ static void cuda_initfn(Object *obj)
|
||||
DEVICE(obj), "adb.0");
|
||||
}
|
||||
|
||||
static Property cuda_properties[] = {
|
||||
DEFINE_PROP_UINT64("frequency", CUDAState, frequency, 0),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
static void cuda_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
@@ -720,6 +736,7 @@ static void cuda_class_init(ObjectClass *oc, void *data)
|
||||
dc->realize = cuda_realizefn;
|
||||
dc->reset = cuda_reset;
|
||||
dc->vmsd = &vmstate_cuda;
|
||||
dc->props = cuda_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo cuda_type_info = {
|
||||
|
||||
+17
-2
@@ -42,6 +42,7 @@ typedef struct MacIOState
|
||||
void *dbdma;
|
||||
MemoryRegion *pic_mem;
|
||||
MemoryRegion *escc_mem;
|
||||
uint64_t frequency;
|
||||
} MacIOState;
|
||||
|
||||
#define OLDWORLD_MACIO(obj) \
|
||||
@@ -243,13 +244,18 @@ static void timer_write(void *opaque, hwaddr addr, uint64_t value,
|
||||
static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
uint64_t systime = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
uint64_t kltime;
|
||||
|
||||
kltime = muldiv64(systime, 4194300, get_ticks_per_sec() * 4);
|
||||
kltime = muldiv64(kltime, 18432000, 1048575);
|
||||
|
||||
switch (addr) {
|
||||
case 0x38:
|
||||
value = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
value = kltime;
|
||||
break;
|
||||
case 0x3c:
|
||||
value = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) >> 32;
|
||||
value = kltime >> 32;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -346,12 +352,19 @@ static void macio_newworld_class_init(ObjectClass *oc, void *data)
|
||||
pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL;
|
||||
}
|
||||
|
||||
static Property macio_properties[] = {
|
||||
DEFINE_PROP_UINT64("frequency", MacIOState, frequency, 0),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
static void macio_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
k->vendor_id = PCI_VENDOR_ID_APPLE;
|
||||
k->class_id = PCI_CLASS_OTHERS << 8;
|
||||
dc->props = macio_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo macio_oldworld_type_info = {
|
||||
@@ -398,6 +411,8 @@ void macio_init(PCIDevice *d,
|
||||
macio_state->escc_mem = escc_mem;
|
||||
/* Note: this code is strongly inspirated from the corresponding code
|
||||
in PearPC */
|
||||
qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "frequency",
|
||||
macio_state->frequency);
|
||||
|
||||
qdev_init_nofail(DEVICE(d));
|
||||
}
|
||||
|
||||
+10
-3
@@ -72,7 +72,14 @@ typedef uint64_t vlan_bd_t;
|
||||
#define VLAN_RXQ_BD_OFF 0
|
||||
#define VLAN_FILTER_BD_OFF 8
|
||||
#define VLAN_RX_BDS_OFF 16
|
||||
#define VLAN_MAX_BUFS ((SPAPR_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF) / 8)
|
||||
/*
|
||||
* The final 8 bytes of the buffer list is a counter of frames dropped
|
||||
* because there was not a buffer in the buffer list capable of holding
|
||||
* the frame. We must avoid it, or the operating system will report garbage
|
||||
* for this statistic.
|
||||
*/
|
||||
#define VLAN_RX_BDS_LEN (SPAPR_TCE_PAGE_SIZE - VLAN_RX_BDS_OFF - 8)
|
||||
#define VLAN_MAX_BUFS (VLAN_RX_BDS_LEN / 8)
|
||||
|
||||
#define TYPE_VIO_SPAPR_VLAN_DEVICE "spapr-vlan"
|
||||
#define VIO_SPAPR_VLAN_DEVICE(obj) \
|
||||
@@ -119,7 +126,7 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
|
||||
|
||||
do {
|
||||
buf_ptr += 8;
|
||||
if (buf_ptr >= SPAPR_TCE_PAGE_SIZE) {
|
||||
if (buf_ptr >= (VLAN_RX_BDS_LEN + VLAN_RX_BDS_OFF)) {
|
||||
buf_ptr = VLAN_RX_BDS_OFF;
|
||||
}
|
||||
|
||||
@@ -397,7 +404,7 @@ static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu,
|
||||
|
||||
do {
|
||||
dev->add_buf_ptr += 8;
|
||||
if (dev->add_buf_ptr >= SPAPR_TCE_PAGE_SIZE) {
|
||||
if (dev->add_buf_ptr >= (VLAN_RX_BDS_LEN + VLAN_RX_BDS_OFF)) {
|
||||
dev->add_buf_ptr = VLAN_RX_BDS_OFF;
|
||||
}
|
||||
|
||||
|
||||
+44
-26
@@ -26,6 +26,7 @@
|
||||
#include "hw/nvram/openbios_firmware_abi.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/ppc/mac.h"
|
||||
#include <zlib.h>
|
||||
|
||||
/* debug NVR */
|
||||
//#define DEBUG_NVR
|
||||
@@ -39,29 +40,6 @@
|
||||
|
||||
#define DEF_SYSTEM_SIZE 0xc10
|
||||
|
||||
/* Direct access to NVRAM */
|
||||
uint8_t macio_nvram_read(MacIONVRAMState *s, uint32_t addr)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
if (addr < s->size) {
|
||||
ret = s->data[addr];
|
||||
} else {
|
||||
ret = -1;
|
||||
}
|
||||
NVR_DPRINTF("read addr %04" PRIx32 " val %" PRIx8 "\n", addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void macio_nvram_write(MacIONVRAMState *s, uint32_t addr, uint8_t val)
|
||||
{
|
||||
NVR_DPRINTF("write addr %04" PRIx32 " val %" PRIx8 "\n", addr, val);
|
||||
if (addr < s->size) {
|
||||
s->data[addr] = val;
|
||||
}
|
||||
}
|
||||
|
||||
/* macio style NVRAM device */
|
||||
static void macio_nvram_writeb(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned size)
|
||||
@@ -89,6 +67,10 @@ static uint64_t macio_nvram_readb(void *opaque, hwaddr addr,
|
||||
static const MemoryRegionOps macio_nvram_ops = {
|
||||
.read = macio_nvram_readb,
|
||||
.write = macio_nvram_writeb,
|
||||
.valid.min_access_size = 1,
|
||||
.valid.max_access_size = 4,
|
||||
.impl.min_access_size = 1,
|
||||
.impl.max_access_size = 1,
|
||||
.endianness = DEVICE_BIG_ENDIAN,
|
||||
};
|
||||
|
||||
@@ -156,15 +138,16 @@ static void macio_nvram_register_types(void)
|
||||
}
|
||||
|
||||
/* Set up a system OpenBIOS NVRAM partition */
|
||||
void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len)
|
||||
static void pmac_format_nvram_partition_of(MacIONVRAMState *nvr, int off,
|
||||
int len)
|
||||
{
|
||||
unsigned int i;
|
||||
uint32_t start = 0, end;
|
||||
uint32_t start = off, end;
|
||||
struct OpenBIOS_nvpart_v1 *part_header;
|
||||
|
||||
// OpenBIOS nvram variables
|
||||
// Variable partition
|
||||
part_header = (struct OpenBIOS_nvpart_v1 *)nvr->data;
|
||||
part_header = (struct OpenBIOS_nvpart_v1 *)&nvr->data[start];
|
||||
part_header->signature = OPENBIOS_PART_SYSTEM;
|
||||
pstrcpy(part_header->name, sizeof(part_header->name), "system");
|
||||
|
||||
@@ -192,4 +175,39 @@ void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len)
|
||||
OpenBIOS_finish_partition(part_header, end - start);
|
||||
}
|
||||
|
||||
#define OSX_NVRAM_SIGNATURE (0x5A)
|
||||
|
||||
/* Set up a Mac OS X NVRAM partition */
|
||||
static void pmac_format_nvram_partition_osx(MacIONVRAMState *nvr, int off,
|
||||
int len)
|
||||
{
|
||||
uint32_t start = off;
|
||||
struct OpenBIOS_nvpart_v1 *part_header;
|
||||
unsigned char *data = &nvr->data[start];
|
||||
|
||||
/* empty partition */
|
||||
part_header = (struct OpenBIOS_nvpart_v1 *)data;
|
||||
part_header->signature = OSX_NVRAM_SIGNATURE;
|
||||
pstrcpy(part_header->name, sizeof(part_header->name), "wwwwwwwwwwww");
|
||||
|
||||
OpenBIOS_finish_partition(part_header, len);
|
||||
|
||||
/* Generation */
|
||||
stl_be_p(&data[20], 2);
|
||||
|
||||
/* Adler32 checksum */
|
||||
stl_be_p(&data[16], adler32(0, &data[20], len - 20));
|
||||
}
|
||||
|
||||
/* Set up NVRAM with OF and OSX partitions */
|
||||
void pmac_format_nvram_partition(MacIONVRAMState *nvr, int len)
|
||||
{
|
||||
/*
|
||||
* Mac OS X expects side "B" of the flash at the second half of NVRAM,
|
||||
* so we use half of the chip for OF and the other half for a free OSX
|
||||
* partition.
|
||||
*/
|
||||
pmac_format_nvram_partition_of(nvr, 0, len / 2);
|
||||
pmac_format_nvram_partition_osx(nvr, len / 2, len / 2);
|
||||
}
|
||||
type_init(macio_nvram_register_types)
|
||||
|
||||
+2
-2
@@ -57,6 +57,7 @@ typedef struct CUDATimer {
|
||||
uint16_t counter_value;
|
||||
int64_t load_time;
|
||||
int64_t next_irq_time;
|
||||
uint64_t frequency;
|
||||
QEMUTimer *timer;
|
||||
} CUDATimer;
|
||||
|
||||
@@ -97,6 +98,7 @@ typedef struct CUDAState {
|
||||
CUDATimer timers[2];
|
||||
|
||||
uint32_t tick_offset;
|
||||
uint64_t frequency;
|
||||
|
||||
uint8_t last_b;
|
||||
uint8_t last_acr;
|
||||
@@ -178,6 +180,4 @@ typedef struct MacIONVRAMState {
|
||||
} MacIONVRAMState;
|
||||
|
||||
void pmac_format_nvram_partition (MacIONVRAMState *nvr, int len);
|
||||
uint8_t macio_nvram_read(MacIONVRAMState *s, uint32_t addr);
|
||||
void macio_nvram_write(MacIONVRAMState *s, uint32_t addr, uint8_t val);
|
||||
#endif /* !defined(__PPC_MAC_H__) */
|
||||
|
||||
+28
-4
@@ -176,6 +176,8 @@ static void ppc_core99_init(MachineState *machine)
|
||||
SysBusDevice *s;
|
||||
DeviceState *dev;
|
||||
int *token = g_new(int, 1);
|
||||
hwaddr nvram_addr = 0xFFF04000;
|
||||
uint64_t tbfreq;
|
||||
|
||||
linux_boot = (kernel_filename != NULL);
|
||||
|
||||
@@ -372,6 +374,14 @@ static void ppc_core99_init(MachineState *machine)
|
||||
pci_bus = pci_pmac_init(pic, get_system_memory(), get_system_io());
|
||||
machine_arch = ARCH_MAC99;
|
||||
}
|
||||
|
||||
/* Timebase Frequency */
|
||||
if (kvm_enabled()) {
|
||||
tbfreq = kvmppc_get_tbfreq();
|
||||
} else {
|
||||
tbfreq = TBFREQ;
|
||||
}
|
||||
|
||||
/* init basic PC hardware */
|
||||
escc_mem = escc_init(0, pic[0x25], pic[0x24],
|
||||
serial_hds[0], serial_hds[1], ESCC_CLOCK, 4);
|
||||
@@ -385,6 +395,7 @@ static void ppc_core99_init(MachineState *machine)
|
||||
qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE DMA */
|
||||
qdev_connect_gpio_out(dev, 3, pic[0x0e]); /* IDE */
|
||||
qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE DMA */
|
||||
qdev_prop_set_uint64(dev, "frequency", tbfreq);
|
||||
macio_init(macio, pic_mem, escc_bar);
|
||||
|
||||
/* We only emulate 2 out of 3 IDE controllers for now */
|
||||
@@ -426,11 +437,18 @@ static void ppc_core99_init(MachineState *machine)
|
||||
}
|
||||
|
||||
/* The NewWorld NVRAM is not located in the MacIO device */
|
||||
#ifdef CONFIG_KVM
|
||||
if (kvm_enabled() && getpagesize() > 4096) {
|
||||
/* We can't combine read-write and read-only in a single page, so
|
||||
move the NVRAM out of ROM again for KVM */
|
||||
nvram_addr = 0xFFE00000;
|
||||
}
|
||||
#endif
|
||||
dev = qdev_create(NULL, TYPE_MACIO_NVRAM);
|
||||
qdev_prop_set_uint32(dev, "size", 0x2000);
|
||||
qdev_prop_set_uint32(dev, "it_shift", 1);
|
||||
qdev_init_nofail(dev);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xFFF04000);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, nvram_addr);
|
||||
nvr = MACIO_NVRAM(dev);
|
||||
pmac_format_nvram_partition(nvr, 0x2000);
|
||||
/* No PCI init: the BIOS will do it */
|
||||
@@ -461,28 +479,34 @@ static void ppc_core99_init(MachineState *machine)
|
||||
#ifdef CONFIG_KVM
|
||||
uint8_t *hypercall;
|
||||
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());
|
||||
hypercall = g_malloc(16);
|
||||
kvmppc_get_hypercall(env, hypercall, 16);
|
||||
fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid());
|
||||
#endif
|
||||
} else {
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ);
|
||||
}
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, tbfreq);
|
||||
/* Mac OS X requires a "known good" clock-frequency value; pass it one. */
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_NVRAM_ADDR, nvram_addr);
|
||||
|
||||
qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
|
||||
}
|
||||
|
||||
static int core99_kvm_type(const char *arg)
|
||||
{
|
||||
/* Always force PR KVM */
|
||||
return 2;
|
||||
}
|
||||
|
||||
static QEMUMachine core99_machine = {
|
||||
.name = "mac99",
|
||||
.desc = "Mac99 based PowerMAC",
|
||||
.init = ppc_core99_init,
|
||||
.max_cpus = MAX_CPUS,
|
||||
.default_boot_order = "cd",
|
||||
.kvm_type = core99_kvm_type,
|
||||
};
|
||||
|
||||
static void core99_machine_init(void)
|
||||
|
||||
+17
-3
@@ -103,6 +103,7 @@ static void ppc_heathrow_init(MachineState *machine)
|
||||
uint16_t ppc_boot_device;
|
||||
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
||||
void *fw_cfg;
|
||||
uint64_t tbfreq;
|
||||
|
||||
linux_boot = (kernel_filename != NULL);
|
||||
|
||||
@@ -250,6 +251,13 @@ static void ppc_heathrow_init(MachineState *machine)
|
||||
}
|
||||
}
|
||||
|
||||
/* Timebase Frequency */
|
||||
if (kvm_enabled()) {
|
||||
tbfreq = kvmppc_get_tbfreq();
|
||||
} else {
|
||||
tbfreq = TBFREQ;
|
||||
}
|
||||
|
||||
/* init basic PC hardware */
|
||||
if (PPC_INPUT(env) != PPC_FLAGS_INPUT_6xx) {
|
||||
hw_error("Only 6xx bus is supported on heathrow machine\n");
|
||||
@@ -278,6 +286,7 @@ static void ppc_heathrow_init(MachineState *machine)
|
||||
qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE-0 DMA */
|
||||
qdev_connect_gpio_out(dev, 3, pic[0x0E]); /* IDE-1 */
|
||||
qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE-1 DMA */
|
||||
qdev_prop_set_uint64(dev, "frequency", tbfreq);
|
||||
macio_init(macio, pic_mem, escc_bar);
|
||||
|
||||
macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio),
|
||||
@@ -330,15 +339,13 @@ static void ppc_heathrow_init(MachineState *machine)
|
||||
#ifdef CONFIG_KVM
|
||||
uint8_t *hypercall;
|
||||
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());
|
||||
hypercall = g_malloc(16);
|
||||
kvmppc_get_hypercall(env, hypercall, 16);
|
||||
fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid());
|
||||
#endif
|
||||
} else {
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ);
|
||||
}
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, tbfreq);
|
||||
/* Mac OS X requires a "known good" clock-frequency value; pass it one. */
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ);
|
||||
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ);
|
||||
@@ -346,6 +353,12 @@ static void ppc_heathrow_init(MachineState *machine)
|
||||
qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
|
||||
}
|
||||
|
||||
static int heathrow_kvm_type(const char *arg)
|
||||
{
|
||||
/* Always force PR KVM */
|
||||
return 2;
|
||||
}
|
||||
|
||||
static QEMUMachine heathrow_machine = {
|
||||
.name = "g3beige",
|
||||
.desc = "Heathrow based PowerMAC",
|
||||
@@ -355,6 +368,7 @@ static QEMUMachine heathrow_machine = {
|
||||
.is_default = 1,
|
||||
#endif
|
||||
.default_boot_order = "cd", /* TOFIX "cad" when Mac floppy is implemented */
|
||||
.kvm_type = heathrow_kvm_type,
|
||||
};
|
||||
|
||||
static void heathrow_machine_init(void)
|
||||
|
||||
+120
-62
@@ -71,6 +71,7 @@
|
||||
*/
|
||||
#define FDT_MAX_SIZE 0x40000
|
||||
#define RTAS_MAX_SIZE 0x10000
|
||||
#define RTAS_MAX_ADDR 0x80000000 /* RTAS must stay below that */
|
||||
#define FW_MAX_SIZE 0x400000
|
||||
#define FW_FILE_NAME "slof.bin"
|
||||
#define FW_OVERHEAD 0x2800000
|
||||
@@ -80,7 +81,7 @@
|
||||
|
||||
#define TIMEBASE_FREQ 512000000ULL
|
||||
|
||||
#define MAX_CPUS 256
|
||||
#define MAX_CPUS 255
|
||||
|
||||
#define PHANDLE_XICP 0x00001111
|
||||
|
||||
@@ -283,6 +284,19 @@ static size_t create_page_sizes_prop(CPUPPCState *env, uint32_t *prop,
|
||||
return (p - prop) * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
static hwaddr spapr_node0_size(void)
|
||||
{
|
||||
if (nb_numa_nodes) {
|
||||
int i;
|
||||
for (i = 0; i < nb_numa_nodes; ++i) {
|
||||
if (numa_info[i].node_mem) {
|
||||
return MIN(pow2floor(numa_info[i].node_mem), ram_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ram_size;
|
||||
}
|
||||
|
||||
#define _FDT(exp) \
|
||||
do { \
|
||||
int ret = (exp); \
|
||||
@@ -319,6 +333,7 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
|
||||
QemuOpts *opts = qemu_opts_find(qemu_find_opts("smp-opts"), NULL);
|
||||
unsigned sockets = opts ? qemu_opt_get_number(opts, "sockets", 0) : 0;
|
||||
uint32_t cpus_per_socket = sockets ? (smp_cpus / sockets) : 1;
|
||||
char *buf;
|
||||
|
||||
add_str(hypertas, "hcall-pft");
|
||||
add_str(hypertas, "hcall-term");
|
||||
@@ -348,6 +363,29 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
|
||||
_FDT((fdt_property_string(fdt, "model", "IBM pSeries (emulated by qemu)")));
|
||||
_FDT((fdt_property_string(fdt, "compatible", "qemu,pseries")));
|
||||
|
||||
/*
|
||||
* Add info to guest to indentify which host is it being run on
|
||||
* and what is the uuid of the guest
|
||||
*/
|
||||
if (kvmppc_get_host_model(&buf)) {
|
||||
_FDT((fdt_property_string(fdt, "host-model", buf)));
|
||||
g_free(buf);
|
||||
}
|
||||
if (kvmppc_get_host_serial(&buf)) {
|
||||
_FDT((fdt_property_string(fdt, "host-serial", buf)));
|
||||
g_free(buf);
|
||||
}
|
||||
|
||||
buf = g_strdup_printf(UUID_FMT, qemu_uuid[0], qemu_uuid[1],
|
||||
qemu_uuid[2], qemu_uuid[3], qemu_uuid[4],
|
||||
qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
|
||||
qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
|
||||
qemu_uuid[11], qemu_uuid[12], qemu_uuid[13],
|
||||
qemu_uuid[14], qemu_uuid[15]);
|
||||
|
||||
_FDT((fdt_property_string(fdt, "vm,uuid", buf)));
|
||||
g_free(buf);
|
||||
|
||||
_FDT((fdt_property_cell(fdt, "#address-cells", 0x2)));
|
||||
_FDT((fdt_property_cell(fdt, "#size-cells", 0x2)));
|
||||
|
||||
@@ -502,6 +540,15 @@ static void *spapr_create_fdt_skel(hwaddr initrd_base,
|
||||
|
||||
_FDT((fdt_property_cell(fdt, "rtas-error-log-max", RTAS_ERROR_LOG_MAX)));
|
||||
|
||||
/*
|
||||
* According to PAPR, rtas ibm,os-term, does not gaurantee a return
|
||||
* back to the guest cpu.
|
||||
*
|
||||
* While an additional ibm,extended-os-term property indicates that
|
||||
* rtas call return will always occur. Set this property.
|
||||
*/
|
||||
_FDT((fdt_property(fdt, "ibm,extended-os-term", NULL, 0)));
|
||||
|
||||
_FDT((fdt_end_node(fdt)));
|
||||
|
||||
/* interrupt controller */
|
||||
@@ -597,72 +644,75 @@ int spapr_h_cas_compose_response(target_ulong addr, target_ulong size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
|
||||
static void spapr_populate_memory_node(void *fdt, int nodeid, hwaddr start,
|
||||
hwaddr size)
|
||||
{
|
||||
uint32_t associativity[] = {cpu_to_be32(0x4), cpu_to_be32(0x0),
|
||||
cpu_to_be32(0x0), cpu_to_be32(0x0),
|
||||
cpu_to_be32(0x0)};
|
||||
uint32_t associativity[] = {
|
||||
cpu_to_be32(0x4), /* length */
|
||||
cpu_to_be32(0x0), cpu_to_be32(0x0),
|
||||
cpu_to_be32(0x0), cpu_to_be32(nodeid)
|
||||
};
|
||||
char mem_name[32];
|
||||
hwaddr node0_size, mem_start, node_size;
|
||||
uint64_t mem_reg_property[2];
|
||||
int i, off;
|
||||
int off;
|
||||
|
||||
/* memory node(s) */
|
||||
if (nb_numa_nodes > 1 && numa_info[0].node_mem < ram_size) {
|
||||
node0_size = numa_info[0].node_mem;
|
||||
} else {
|
||||
node0_size = ram_size;
|
||||
}
|
||||
mem_reg_property[0] = cpu_to_be64(start);
|
||||
mem_reg_property[1] = cpu_to_be64(size);
|
||||
|
||||
/* RMA */
|
||||
mem_reg_property[0] = 0;
|
||||
mem_reg_property[1] = cpu_to_be64(spapr->rma_size);
|
||||
off = fdt_add_subnode(fdt, 0, "memory@0");
|
||||
sprintf(mem_name, "memory@" TARGET_FMT_lx, start);
|
||||
off = fdt_add_subnode(fdt, 0, mem_name);
|
||||
_FDT(off);
|
||||
_FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
|
||||
_FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
|
||||
sizeof(mem_reg_property))));
|
||||
_FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
|
||||
sizeof(associativity))));
|
||||
}
|
||||
|
||||
/* RAM: Node 0 */
|
||||
if (node0_size > spapr->rma_size) {
|
||||
mem_reg_property[0] = cpu_to_be64(spapr->rma_size);
|
||||
mem_reg_property[1] = cpu_to_be64(node0_size - spapr->rma_size);
|
||||
static int spapr_populate_memory(sPAPREnvironment *spapr, void *fdt)
|
||||
{
|
||||
hwaddr mem_start, node_size;
|
||||
int i, nb_nodes = nb_numa_nodes;
|
||||
NodeInfo *nodes = numa_info;
|
||||
NodeInfo ramnode;
|
||||
|
||||
sprintf(mem_name, "memory@" TARGET_FMT_lx, spapr->rma_size);
|
||||
off = fdt_add_subnode(fdt, 0, mem_name);
|
||||
_FDT(off);
|
||||
_FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
|
||||
_FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
|
||||
sizeof(mem_reg_property))));
|
||||
_FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
|
||||
sizeof(associativity))));
|
||||
/* No NUMA nodes, assume there is just one node with whole RAM */
|
||||
if (!nb_numa_nodes) {
|
||||
nb_nodes = 1;
|
||||
ramnode.node_mem = ram_size;
|
||||
nodes = &ramnode;
|
||||
}
|
||||
|
||||
/* RAM: Node 1 and beyond */
|
||||
mem_start = node0_size;
|
||||
for (i = 1; i < nb_numa_nodes; i++) {
|
||||
mem_reg_property[0] = cpu_to_be64(mem_start);
|
||||
for (i = 0, mem_start = 0; i < nb_nodes; ++i) {
|
||||
if (!nodes[i].node_mem) {
|
||||
continue;
|
||||
}
|
||||
if (mem_start >= ram_size) {
|
||||
node_size = 0;
|
||||
} else {
|
||||
node_size = numa_info[i].node_mem;
|
||||
node_size = nodes[i].node_mem;
|
||||
if (node_size > ram_size - mem_start) {
|
||||
node_size = ram_size - mem_start;
|
||||
}
|
||||
}
|
||||
mem_reg_property[1] = cpu_to_be64(node_size);
|
||||
associativity[3] = associativity[4] = cpu_to_be32(i);
|
||||
sprintf(mem_name, "memory@" TARGET_FMT_lx, mem_start);
|
||||
off = fdt_add_subnode(fdt, 0, mem_name);
|
||||
_FDT(off);
|
||||
_FDT((fdt_setprop_string(fdt, off, "device_type", "memory")));
|
||||
_FDT((fdt_setprop(fdt, off, "reg", mem_reg_property,
|
||||
sizeof(mem_reg_property))));
|
||||
_FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity,
|
||||
sizeof(associativity))));
|
||||
mem_start += node_size;
|
||||
if (!mem_start) {
|
||||
/* ppc_spapr_init() checks for rma_size <= node0_size already */
|
||||
spapr_populate_memory_node(fdt, i, 0, spapr->rma_size);
|
||||
mem_start += spapr->rma_size;
|
||||
node_size -= spapr->rma_size;
|
||||
}
|
||||
for ( ; node_size; ) {
|
||||
hwaddr sizetmp = pow2floor(node_size);
|
||||
|
||||
/* mem_start != 0 here */
|
||||
if (ctzl(mem_start) < ctzl(sizetmp)) {
|
||||
sizetmp = 1ULL << ctzl(mem_start);
|
||||
}
|
||||
|
||||
spapr_populate_memory_node(fdt, i, mem_start, sizetmp);
|
||||
node_size -= sizetmp;
|
||||
mem_start += sizetmp;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -746,6 +796,7 @@ static void spapr_finalize_fdt(sPAPREnvironment *spapr,
|
||||
|
||||
cpu_physical_memory_write(fdt_addr, fdt, fdt_totalsize(fdt));
|
||||
|
||||
g_free(bootlist);
|
||||
g_free(fdt);
|
||||
}
|
||||
|
||||
@@ -792,25 +843,38 @@ static void spapr_reset_htab(sPAPREnvironment *spapr)
|
||||
|
||||
/* Update the RMA size if necessary */
|
||||
if (spapr->vrma_adjust) {
|
||||
hwaddr node0_size = (nb_numa_nodes > 1) ?
|
||||
numa_info[0].node_mem : ram_size;
|
||||
spapr->rma_size = kvmppc_rma_size(node0_size, spapr->htab_shift);
|
||||
spapr->rma_size = kvmppc_rma_size(spapr_node0_size(),
|
||||
spapr->htab_shift);
|
||||
}
|
||||
}
|
||||
|
||||
static void ppc_spapr_reset(void)
|
||||
{
|
||||
PowerPCCPU *first_ppc_cpu;
|
||||
uint32_t rtas_limit;
|
||||
|
||||
/* Reset the hash table & recalc the RMA */
|
||||
spapr_reset_htab(spapr);
|
||||
|
||||
qemu_devices_reset();
|
||||
|
||||
/*
|
||||
* We place the device tree and RTAS just below either the top of the RMA,
|
||||
* or just below 2GB, whichever is lowere, so that it can be
|
||||
* processed with 32-bit real mode code if necessary
|
||||
*/
|
||||
rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR);
|
||||
spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
|
||||
spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
|
||||
|
||||
/* Load the fdt */
|
||||
spapr_finalize_fdt(spapr, spapr->fdt_addr, spapr->rtas_addr,
|
||||
spapr->rtas_size);
|
||||
|
||||
/* Copy RTAS over */
|
||||
cpu_physical_memory_write(spapr->rtas_addr, spapr->rtas_blob,
|
||||
spapr->rtas_size);
|
||||
|
||||
/* Set up the entry state */
|
||||
first_ppc_cpu = POWERPC_CPU(first_cpu);
|
||||
first_ppc_cpu->env.gpr[3] = spapr->fdt_addr;
|
||||
@@ -1227,10 +1291,10 @@ static void ppc_spapr_init(MachineState *machine)
|
||||
MemoryRegion *rma_region;
|
||||
void *rma = NULL;
|
||||
hwaddr rma_alloc_size;
|
||||
hwaddr node0_size = (nb_numa_nodes > 1) ? numa_info[0].node_mem : ram_size;
|
||||
hwaddr node0_size = spapr_node0_size();
|
||||
uint32_t initrd_base = 0;
|
||||
long kernel_size = 0, initrd_size = 0;
|
||||
long load_limit, rtas_limit, fw_size;
|
||||
long load_limit, fw_size;
|
||||
bool kernel_le = false;
|
||||
char *filename;
|
||||
|
||||
@@ -1275,13 +1339,8 @@ static void ppc_spapr_init(MachineState *machine)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* We place the device tree and RTAS just below either the top of the RMA,
|
||||
* or just below 2GB, whichever is lowere, so that it can be
|
||||
* processed with 32-bit real mode code if necessary */
|
||||
rtas_limit = MIN(spapr->rma_size, 0x80000000);
|
||||
spapr->rtas_addr = rtas_limit - RTAS_MAX_SIZE;
|
||||
spapr->fdt_addr = spapr->rtas_addr - FDT_MAX_SIZE;
|
||||
load_limit = spapr->fdt_addr - FW_OVERHEAD;
|
||||
/* Setup a load limit for the ramdisk leaving room for SLOF and FDT */
|
||||
load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD;
|
||||
|
||||
/* We aim for a hash table of size 1/128 the size of RAM. The
|
||||
* normal rule of thumb is 1/64 the size of RAM, but that's much
|
||||
@@ -1349,14 +1408,14 @@ static void ppc_spapr_init(MachineState *machine)
|
||||
}
|
||||
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
|
||||
spapr->rtas_size = load_image_targphys(filename, spapr->rtas_addr,
|
||||
rtas_limit - spapr->rtas_addr);
|
||||
if (spapr->rtas_size < 0) {
|
||||
spapr->rtas_size = get_image_size(filename);
|
||||
spapr->rtas_blob = g_malloc(spapr->rtas_size);
|
||||
if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) {
|
||||
hw_error("qemu: could not load LPAR rtas '%s'\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
if (spapr->rtas_size > RTAS_MAX_SIZE) {
|
||||
hw_error("RTAS too big ! 0x%lx bytes (max is 0x%x)\n",
|
||||
hw_error("RTAS too big ! 0x%zx bytes (max is 0x%x)\n",
|
||||
spapr->rtas_size, RTAS_MAX_SIZE);
|
||||
exit(1);
|
||||
}
|
||||
@@ -1378,7 +1437,6 @@ static void ppc_spapr_init(MachineState *machine)
|
||||
spapr_create_nvram(spapr);
|
||||
|
||||
/* Set up PCI */
|
||||
spapr_pci_msi_init(spapr, SPAPR_PCI_MSI_WINDOW);
|
||||
spapr_pci_rtas_init();
|
||||
|
||||
phb = spapr_create_phb(spapr, 0);
|
||||
|
||||
+11
-11
@@ -712,10 +712,10 @@ static target_ulong h_logical_dcbf(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
static target_ulong h_set_mode_resouce_le(PowerPCCPU *cpu,
|
||||
target_ulong mflags,
|
||||
target_ulong value1,
|
||||
target_ulong value2)
|
||||
static target_ulong h_set_mode_resource_le(PowerPCCPU *cpu,
|
||||
target_ulong mflags,
|
||||
target_ulong value1,
|
||||
target_ulong value2)
|
||||
{
|
||||
CPUState *cs;
|
||||
|
||||
@@ -743,10 +743,10 @@ static target_ulong h_set_mode_resouce_le(PowerPCCPU *cpu,
|
||||
return H_UNSUPPORTED_FLAG;
|
||||
}
|
||||
|
||||
static target_ulong h_set_mode_resouce_addr_trans_mode(PowerPCCPU *cpu,
|
||||
target_ulong mflags,
|
||||
target_ulong value1,
|
||||
target_ulong value2)
|
||||
static target_ulong h_set_mode_resource_addr_trans_mode(PowerPCCPU *cpu,
|
||||
target_ulong mflags,
|
||||
target_ulong value1,
|
||||
target_ulong value2)
|
||||
{
|
||||
CPUState *cs;
|
||||
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
|
||||
@@ -794,11 +794,11 @@ static target_ulong h_set_mode(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
|
||||
switch (resource) {
|
||||
case H_SET_MODE_RESOURCE_LE:
|
||||
ret = h_set_mode_resouce_le(cpu, args[0], args[2], args[3]);
|
||||
ret = h_set_mode_resource_le(cpu, args[0], args[2], args[3]);
|
||||
break;
|
||||
case H_SET_MODE_RESOURCE_ADDR_TRANS_MODE:
|
||||
ret = h_set_mode_resouce_addr_trans_mode(cpu, args[0],
|
||||
args[2], args[3]);
|
||||
ret = h_set_mode_resource_addr_trans_mode(cpu, args[0],
|
||||
args[2], args[3]);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+30
-31
@@ -262,7 +262,6 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
unsigned int irq, max_irqs = 0, num = 0;
|
||||
sPAPRPHBState *phb = NULL;
|
||||
PCIDevice *pdev = NULL;
|
||||
bool msix = false;
|
||||
spapr_pci_msi *msi;
|
||||
int *config_addr_key;
|
||||
|
||||
@@ -300,7 +299,12 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
}
|
||||
|
||||
xics_free(spapr->icp, msi->first_irq, msi->num);
|
||||
spapr_msi_setmsg(pdev, 0, msix, 0, num);
|
||||
if (msi_present(pdev)) {
|
||||
spapr_msi_setmsg(pdev, 0, false, 0, num);
|
||||
}
|
||||
if (msix_present(pdev)) {
|
||||
spapr_msi_setmsg(pdev, 0, true, 0, num);
|
||||
}
|
||||
g_hash_table_remove(phb->msi, &config_addr);
|
||||
|
||||
trace_spapr_pci_msi("Released MSIs", config_addr);
|
||||
@@ -341,7 +345,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
|
||||
}
|
||||
|
||||
/* Setup MSI/MSIX vectors in the device (via cfgspace or MSIX BAR) */
|
||||
spapr_msi_setmsg(pdev, spapr->msi_win_addr, ret_intr_type == RTAS_TYPE_MSIX,
|
||||
spapr_msi_setmsg(pdev, SPAPR_PCI_MSI_WINDOW, ret_intr_type == RTAS_TYPE_MSIX,
|
||||
irq, req_num);
|
||||
|
||||
/* Add MSI device to cache */
|
||||
@@ -465,34 +469,6 @@ static const MemoryRegionOps spapr_msi_ops = {
|
||||
.endianness = DEVICE_LITTLE_ENDIAN
|
||||
};
|
||||
|
||||
void spapr_pci_msi_init(sPAPREnvironment *spapr, hwaddr addr)
|
||||
{
|
||||
uint64_t window_size = 4096;
|
||||
|
||||
/*
|
||||
* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors,
|
||||
* we need to allocate some memory to catch those writes coming
|
||||
* from msi_notify()/msix_notify().
|
||||
* As MSIMessage:addr is going to be the same and MSIMessage:data
|
||||
* is going to be a VIRQ number, 4 bytes of the MSI MR will only
|
||||
* be used.
|
||||
*
|
||||
* For KVM we want to ensure that this memory is a full page so that
|
||||
* our memory slot is of page size granularity.
|
||||
*/
|
||||
#ifdef CONFIG_KVM
|
||||
if (kvm_enabled()) {
|
||||
window_size = getpagesize();
|
||||
}
|
||||
#endif
|
||||
|
||||
spapr->msi_win_addr = addr;
|
||||
memory_region_init_io(&spapr->msiwindow, NULL, &spapr_msi_ops, spapr,
|
||||
"msi", window_size);
|
||||
memory_region_add_subregion(get_system_memory(), spapr->msi_win_addr,
|
||||
&spapr->msiwindow);
|
||||
}
|
||||
|
||||
/*
|
||||
* PHB PCI device
|
||||
*/
|
||||
@@ -512,6 +488,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
char *namebuf;
|
||||
int i;
|
||||
PCIBus *bus;
|
||||
uint64_t msi_window_size = 4096;
|
||||
|
||||
if (sphb->index != -1) {
|
||||
hwaddr windows_base;
|
||||
@@ -604,6 +581,28 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
||||
address_space_init(&sphb->iommu_as, &sphb->iommu_root,
|
||||
sphb->dtbusname);
|
||||
|
||||
/*
|
||||
* As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors,
|
||||
* we need to allocate some memory to catch those writes coming
|
||||
* from msi_notify()/msix_notify().
|
||||
* As MSIMessage:addr is going to be the same and MSIMessage:data
|
||||
* is going to be a VIRQ number, 4 bytes of the MSI MR will only
|
||||
* be used.
|
||||
*
|
||||
* For KVM we want to ensure that this memory is a full page so that
|
||||
* our memory slot is of page size granularity.
|
||||
*/
|
||||
#ifdef CONFIG_KVM
|
||||
if (kvm_enabled()) {
|
||||
msi_window_size = getpagesize();
|
||||
}
|
||||
#endif
|
||||
|
||||
memory_region_init_io(&sphb->msiwindow, NULL, &spapr_msi_ops, spapr,
|
||||
"msi", msi_window_size);
|
||||
memory_region_add_subregion(&sphb->iommu_root, SPAPR_PCI_MSI_WINDOW,
|
||||
&sphb->msiwindow);
|
||||
|
||||
pci_setup_iommu(bus, spapr_pci_dma_iommu, sphb);
|
||||
|
||||
pci_bus_set_route_irq_fn(bus, spapr_route_intx_pin_to_irq);
|
||||
|
||||
@@ -277,6 +277,19 @@ static void rtas_ibm_set_system_parameter(PowerPCCPU *cpu,
|
||||
rtas_st(rets, 0, ret);
|
||||
}
|
||||
|
||||
static void rtas_ibm_os_term(PowerPCCPU *cpu,
|
||||
sPAPREnvironment *spapr,
|
||||
uint32_t token, uint32_t nargs,
|
||||
target_ulong args,
|
||||
uint32_t nret, target_ulong rets)
|
||||
{
|
||||
target_ulong ret = 0;
|
||||
|
||||
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, &error_abort);
|
||||
|
||||
rtas_st(rets, 0, ret);
|
||||
}
|
||||
|
||||
static struct rtas_call {
|
||||
const char *name;
|
||||
spapr_rtas_fn fn;
|
||||
@@ -404,6 +417,8 @@ static void core_rtas_register_types(void)
|
||||
spapr_rtas_register(RTAS_IBM_SET_SYSTEM_PARAMETER,
|
||||
"ibm,set-system-parameter",
|
||||
rtas_ibm_set_system_parameter);
|
||||
spapr_rtas_register(RTAS_IBM_OS_TERM, "ibm,os-term",
|
||||
rtas_ibm_os_term);
|
||||
}
|
||||
|
||||
type_init(core_rtas_register_types)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
int get_image_size(const char *filename);
|
||||
int load_image(const char *filename, uint8_t *addr); /* deprecated */
|
||||
ssize_t load_image_size(const char *filename, void *addr, size_t size);
|
||||
int load_image_targphys(const char *filename, hwaddr,
|
||||
uint64_t max_sz);
|
||||
int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz);
|
||||
|
||||
@@ -70,7 +70,7 @@ struct sPAPRPHBState {
|
||||
|
||||
MemoryRegion memspace, iospace;
|
||||
hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size;
|
||||
MemoryRegion memwindow, iowindow;
|
||||
MemoryRegion memwindow, iowindow, msiwindow;
|
||||
|
||||
uint32_t dma_liobn;
|
||||
AddressSpace iommu_as;
|
||||
|
||||
@@ -92,7 +92,7 @@ enum {
|
||||
#define FW_CFG_PPC_IS_KVM (FW_CFG_ARCH_LOCAL + 0x05)
|
||||
#define FW_CFG_PPC_KVM_HC (FW_CFG_ARCH_LOCAL + 0x06)
|
||||
#define FW_CFG_PPC_KVM_PID (FW_CFG_ARCH_LOCAL + 0x07)
|
||||
/* OpenBIOS has FW_CFG_PPC_NVRAM_ADDR as +0x08 */
|
||||
#define FW_CFG_PPC_NVRAM_ADDR (FW_CFG_ARCH_LOCAL + 0x08)
|
||||
#define FW_CFG_PPC_BUSFREQ (FW_CFG_ARCH_LOCAL + 0x09)
|
||||
|
||||
#define PPC_SERIAL_MM_BAUDBASE 399193
|
||||
|
||||
@@ -13,8 +13,6 @@ struct sPAPRNVRAM;
|
||||
typedef struct sPAPREnvironment {
|
||||
struct VIOsPAPRBus *vio_bus;
|
||||
QLIST_HEAD(, sPAPRPHBState) phbs;
|
||||
hwaddr msi_win_addr;
|
||||
MemoryRegion msiwindow;
|
||||
struct sPAPRNVRAM *nvram;
|
||||
XICSState *icp;
|
||||
|
||||
@@ -24,7 +22,8 @@ typedef struct sPAPREnvironment {
|
||||
hwaddr rma_size;
|
||||
int vrma_adjust;
|
||||
hwaddr fdt_addr, rtas_addr;
|
||||
long rtas_size;
|
||||
ssize_t rtas_size;
|
||||
void *rtas_blob;
|
||||
void *fdt_skel;
|
||||
target_ulong entry_point;
|
||||
uint64_t rtc_offset;
|
||||
@@ -382,9 +381,8 @@ int spapr_allocate_irq_block(int num, bool lsi, bool msi);
|
||||
#define RTAS_GET_SENSOR_STATE (RTAS_TOKEN_BASE + 0x1D)
|
||||
#define RTAS_IBM_CONFIGURE_CONNECTOR (RTAS_TOKEN_BASE + 0x1E)
|
||||
#define RTAS_IBM_OS_TERM (RTAS_TOKEN_BASE + 0x1F)
|
||||
#define RTAS_IBM_EXTENDED_OS_TERM (RTAS_TOKEN_BASE + 0x20)
|
||||
|
||||
#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x21)
|
||||
#define RTAS_TOKEN_MAX (RTAS_TOKEN_BASE + 0x20)
|
||||
|
||||
/* RTAS ibm,get-system-parameter token values */
|
||||
#define RTAS_SYSPARM_SPLPAR_CHARACTERISTICS 20
|
||||
|
||||
@@ -303,6 +303,8 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cpu);
|
||||
|
||||
int kvm_check_extension(KVMState *s, unsigned int extension);
|
||||
|
||||
int kvm_vm_check_extension(KVMState *s, unsigned int extension);
|
||||
|
||||
#define kvm_vm_enable_cap(s, capability, cap_flags, ...) \
|
||||
({ \
|
||||
struct kvm_enable_cap cap = { \
|
||||
|
||||
@@ -493,6 +493,19 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int kvm_vm_check_extension(KVMState *s, unsigned int extension)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = kvm_vm_ioctl(s, KVM_CHECK_EXTENSION, extension);
|
||||
if (ret < 0) {
|
||||
/* VM wide version not implemented, use global one instead */
|
||||
ret = kvm_check_extension(s, extension);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int kvm_set_ioeventfd_mmio(int fd, hwaddr addr, uint32_t val,
|
||||
bool assign, uint32_t size, bool datamatch)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user