[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH ARM v4 07/12] mini-os: initial ARM support
On 06/23/2014 04:10 PM, Thomas Leonard wrote: > On 18 June 2014 23:40, Julien Grall <julien.grall@xxxxxxxxxx> wrote: > Hi Julien, Hi Thomas, >> >> >>> +void set_vtimer_compare(uint64_t value) { >>> + uint32_t x, y; >>> + >>> + DEBUG("New CompareValue : %llx\n", value); >>> + x = 0xFFFFFFFFULL & value; >>> + y = (value >> 32) & 0xFFFFFFFF; >>> + >>> + __asm__ __volatile__("mcrr p15, 3, %0, %1, c14\n" >>> + "isb"::"r"(x), "r"(y)); >>> + >>> + __asm__ __volatile__("mov %0, #0x1\n" >>> + "mcr p15, 0, %0, c14, c3, 1\n" /* Enable timer and unmask the >>> output signal */ >>> + "isb":"=r"(x)); >> >> >> I don't think you need to add an isb per instruction. One should be enough. > > Actually, do we need one at all? Setting the timer shouldn't affect > the instruction pipline, I think. The isb is also used to make sure that an access to a system control registers (such as setting the page table) has finished before executing the next instruction. >> [..] >> >> >>> diff --git a/extras/mini-os/drivers/gic.c b/extras/mini-os/drivers/gic.c >>> new file mode 100644 >>> index 0000000..3141830 >>> --- /dev/null >>> +++ b/extras/mini-os/drivers/gic.c >>> @@ -0,0 +1,187 @@ >>> +// ARM GIC implementation >>> + >>> +#include <mini-os/os.h> >>> +#include <mini-os/hypervisor.h> >>> + >>> +//#define VGIC_DEBUG >>> +#ifdef VGIC_DEBUG >>> +#define DEBUG(_f, _a...) \ >>> + DEBUG("MINI_OS(file=vgic.c, line=%d) " _f , __LINE__, ## _a) >>> +#else >>> +#define DEBUG(_f, _a...) ((void)0) >>> +#endif >>> + >>> +extern void (*IRQ_handler)(void); >>> + >>> +struct gic { >>> + volatile char *gicd_base; >>> + volatile char *gicc_base; >>> +}; >>> + >>> +static struct gic gic; >>> + >>> +// Distributor Interface >>> +#define GICD_CTLR 0x0 >>> +#define GICD_ISENABLER 0x100 >>> +#define GICD_PRIORITY 0x400 >> >> >> You use the right name for every macro except this one. I would rename it to >> GICD_IPRIORITYR to stay consistent. > > Done. Thanks ! >>> +static inline void REG_WRITE32(volatile uint32_t *addr, unsigned int >>> value) >>> +{ >>> + __asm__ __volatile__("str %0, [%1]"::"r"(value), "r"(addr)); >>> + wmb(); >>> +} >>> + > > Do we need inline assembler to write these values? I'd imagine that a > plain C store to a volatile 32-bit pointer would always do the same > thing. The compiler may do strange things to store the value, such as 4 byte-store instead of a word-store. So we have to use inline assembly to make sure the correct access will be done. >>> +{ >>> + uint32_t value; >>> + value = REG_READ32(REG(gicd(gic, GICD_PRIORITY)) + irq_number); >> >> >> There is 4 interrupts describe per register, this should be (irq_number & >> ~3). > > Or should it be (irq_number >> 2)? REG casts to uint32_t. It's the same :). >>> +} >>> + >>> +static void gic_route_interrupt(struct gic *gic, unsigned char >>> irq_number, unsigned char cpu_set) >>> +{ >>> + uint32_t value; >>> + value = REG_READ32(REG(gicd(gic, GICD_ITARGETSR)) + irq_number); >> >> >> Same remark as gic_set_priority here. >> >> >>> + value &= ~(0xff << (8 * (irq_number & 0x3))); // set priority to '0' >>> + value |= cpu_set << (8 * (irq_number & 0x3)); // add our priority >> >> >> The comments are wrong in the 2 lines above. >> >> >>> + REG_WRITE32(REG(gicd(gic, GICD_ITARGETSR)) + irq_number, value); >> >> >> irq_number & ~3; > > The ARM Generic Interrupt Controller Architecture Specification says > "These registers are byte-accessible.". So we should be able to write > the byte directly. I thought this might work: > > static void gic_route_interrupt(struct gic *gic, int irq_number, > unsigned char cpu_set) > { > gicd(gic, GICD_ITARGETSR)[irq_number] = cpu_set; > wmb(); > } This code looks good to me. > > But it doesn't, because Xen's write_ignore handler (vgic.c:656 on the > 4.4 branch) does: > > write_ignore: > if ( dabt.size != 2 ) goto bad_width; > > Bug? This is a bug in Xen. I think, write_ignore should just ignore the write rather checking badly the size. Can you send a patch for it? >>> +} >>> + >>> +#define local_irq_save(x) { \ >>> + __asm__ __volatile__("mrs %0, cpsr;cpsid i; and %0, %0, >>> #0x80":"=r"(x)::"memory"); \ >>> +} >>> + >>> +#define local_irq_restore(x) { \ >>> + __asm__ __volatile__("msr cpsr_c, %0"::"r"(x):"memory"); \ >>> +} >> >> >> If you mask the result in local_irq_save, and use this value directly is >> local_irq_restore, you will disable by mistake the Asynchronous Abort >> exception.... >> >> You have to remove the and %0... at the end. > > This makes schedule() fail, because it checks whether the result is zero. > Perhaps we should continue to mask it, but only apply the IRQ bit in > local_irq_restore? I would prefer to change the schedule code if it's possible to keep local_irq_restore as simple as possible. This helper is often used. I don't know much the code of schedule. Why don't we only check that the IRQ are disabled rather than call local_irq_{save,restore}? >>> +#define local_irq_disable() __cli() >>> +#define local_irq_enable() __sti() >>> + >>> +#if defined(__arm__) >>> +#define mb() __asm__("dmb"); >>> +#define rmb() __asm__("dmb"); >>> +#define wmb() __asm__("dmb"); >> >> >> I suspect you want to dsb here. You want to make sure that every memory >> access has finished avoid executing new instruction until this is done. > > Is this necessary? As I understand it, using Xen's ring system > requires a strict ordering (dmb), but we don't need to stall the > processor waiting for each write to complete before going on to the > next one. Is it written somewhere? FIY, Linux is using dsb with ring system. Even tho, I think dmb is fine here. I'd like confirmation for either Ian C. or Stefano. Futhermore, there is other place in mini-os (such as the GIC) where I think we have to use dsb. >>> +#define unlikely(x) __builtin_expect((x),0) >>> +#define likely(x) __builtin_expect((x),1) >> >> >> Can't it be common with x86? > > Which header file should it go in? I don't know much mini-os, but I would add either in lib.h or create a new header compiler.h. >> [..] >> >> >>> +#if defined(__i386__) || defined(__arm__) >>> typedef long long quad_t; >>> typedef unsigned long long u_quad_t; >>> >>> @@ -40,7 +40,7 @@ typedef unsigned long u_quad_t; >>> typedef struct { unsigned long pte; } pte_t; >>> #endif /* __i386__ || __x86_64__ */ >>> >>> -#ifdef __x86_64__ >>> +#if defined(__x86_64__) || defined(__aarch64__) >>> #define __pte(x) ((pte_t) { (x) } ) >> >> >> This looks wrong to me. The pte layout is exactly the same on arm32 and >> arm64. Hence, this is only used in the x86 code. Please either move pte_t in >> x86 part or define it correctly on ARM... > > Moved to x86. Actually, this simplifies things further, because it can > go in the separate hypercall-*.h files and lose the #ifdef completely. Great, thanks! Regards, -- Julien Grall _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |